From e60adb50ea0153996abac01e7ee8a2eafae815b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 18:01:50 +0200 Subject: [PATCH 01/92] chore(ci): bump version to 2.22.0 (#2840) Co-authored-by: Powertools for AWS Lambda (Python) bot --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index f22bb031e1d..3da2c288c98 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "2.21.0" +VERSION = "2.22.0" diff --git a/pyproject.toml b/pyproject.toml index bcc3bb9610f..0b3a84660e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "2.21.0" +version = "2.22.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"] From e32e8d1e0e61d579cbb19d1086185a0f48eb6644 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 18:02:38 +0200 Subject: [PATCH 02/92] chore(ci): layer docs update (#2841) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 21 ++--- docs/index.md | 128 ++++++++++++++--------------- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- examples/tracer/sam/template.yaml | 2 +- 5 files changed, 72 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbe488d678d..293e92155c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,24 +4,12 @@ # Unreleased -## Documentation - -* **community:** new batch processing article ([#2828](https://github.com/aws-powertools/powertools-lambda-python/issues/2828)) -* **parameters:** improve readability on error handling get_parameter… ([#2833](https://github.com/aws-powertools/powertools-lambda-python/issues/2833)) - -## Features - -* **general:** add support for Python 3.11 ([#2820](https://github.com/aws-powertools/powertools-lambda-python/issues/2820)) + +## [v2.22.0] - 2023-07-25 ## Maintenance -* **ci:** add baking time for layer build ([#2834](https://github.com/aws-powertools/powertools-lambda-python/issues/2834)) -* **ci:** build changelog on a schedule only ([#2832](https://github.com/aws-powertools/powertools-lambda-python/issues/2832)) -* **deps:** bump actions/setup-python from 4.6.1 to 4.7.0 ([#2821](https://github.com/aws-powertools/powertools-lambda-python/issues/2821)) -* **deps-dev:** bump ruff from 0.0.279 to 0.0.280 ([#2836](https://github.com/aws-powertools/powertools-lambda-python/issues/2836)) -* **deps-dev:** bump ruff from 0.0.278 to 0.0.279 ([#2822](https://github.com/aws-powertools/powertools-lambda-python/issues/2822)) -* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.0 to 1.28.10 ([#2837](https://github.com/aws-powertools/powertools-lambda-python/issues/2837)) -* **deps-dev:** bump cfn-lint from 0.78.1 to 0.78.2 ([#2823](https://github.com/aws-powertools/powertools-lambda-python/issues/2823)) +* version bump @@ -3597,7 +3585,8 @@ * Merge pull request [#5](https://github.com/aws-powertools/powertools-lambda-python/issues/5) from jfuss/feat/python38 -[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.21.0...HEAD +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.22.0...HEAD +[v2.22.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.21.0...v2.22.0 [v2.21.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.20.0...v2.21.0 [v2.20.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.19.0...v2.20.0 [v2.19.0]: https://github.com/aws-powertools/powertools-lambda-python/compare/v2.18.0...v2.19.0 diff --git a/docs/index.md b/docs/index.md index 210462bc5b6..dff39e1e20b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,8 +26,8 @@ Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverles You can install Powertools for AWS Lambda (Python) using one of the following options: -* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39**](# "Replace {region} with your AWS region, e.g., eu-west-1"){: .copyMe}:clipboard: -* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39**](# "Replace {region} with your AWS region, e.g., eu-west-1"){: .copyMe}:clipboard: +* **Lambda Layer (x86_64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40**](# "Replace {region} with your AWS region, e.g., eu-west-1"){: .copyMe}:clipboard: +* **Lambda Layer (arm64)**: [**arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40**](# "Replace {region} with your AWS region, e.g., eu-west-1"){: .copyMe}:clipboard: * **Pip**: **[`pip install "aws-lambda-powertools"`](#){: .copyMe}:clipboard:** !!! question "Looking for Pip signed releases? [Learn more about verifying signed builds](./security.md#verifying-signed-builds)" @@ -80,60 +80,60 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-south-2` | [arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-central-2` | [arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-south-2` | [arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `me-central-1` | [arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:39](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-south-2` | [arn:aws:lambda:ap-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-central-2` | [arn:aws:lambda:eu-central-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-south-2` | [arn:aws:lambda:eu-south-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `me-central-1` | [arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | === "arm64" | Region | Layer ARN | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | - | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40](#){: .copyMe}:clipboard: | ??? note "Note: Click to expand and copy code snippets for popular frameworks" @@ -146,7 +146,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd Type: AWS::Serverless::Function Properties: Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 ``` === "Serverless framework" @@ -156,7 +156,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd hello: handler: lambda_function.lambda_handler layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 ``` === "CDK" @@ -172,7 +172,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -221,7 +221,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } @@ -274,7 +274,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 ❯ amplify push -y @@ -285,7 +285,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 ? Do you want to edit the local lambda function now? No ``` @@ -299,7 +299,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd Properties: Architectures: [arm64] Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40 ``` === "Serverless framework" @@ -310,7 +310,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd handler: lambda_function.lambda_handler architecture: arm64 layers: - - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39 + - arn:aws:lambda:${aws:region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40 ``` === "CDK" @@ -326,7 +326,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39" + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40" ) aws_lambda.Function(self, 'sample-app-lambda', @@ -376,7 +376,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40"] architectures = ["arm64"] source_code_hash = filebase64sha256("lambda_function_payload.zip") @@ -432,7 +432,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40 ❯ amplify push -y @@ -443,7 +443,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:39 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:eu-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:40 ? Do you want to edit the local lambda function now? No ``` @@ -451,7 +451,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index 358696def9a..a72b96f32e2 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -14,7 +14,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 Resources: LoggerLambdaHandlerExample: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index 3bb19572774..50a2964bc4b 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -15,7 +15,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 Resources: CaptureLambdaHandlerExample: diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index e76f47c0f1c..3eb6ef0acd0 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -13,7 +13,7 @@ Globals: Layers: # Find the latest Layer version in the official documentation # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:39 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 Resources: CaptureLambdaHandlerExample: From 9917d0a02447676658e6fa3b7ff4c25514ebae55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:27:47 +0100 Subject: [PATCH 03/92] chore(deps): bump pydantic from 1.10.11 to 1.10.12 (#2846) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 74 ++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/poetry.lock b/poetry.lock index 3b196373e24..ef30969aa9f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1728,47 +1728,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.11" +version = "1.10.12" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"}, - {file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"}, - {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"}, - {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"}, - {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"}, - {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"}, - {file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"}, - {file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"}, - {file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"}, - {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"}, - {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"}, - {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"}, - {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"}, - {file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"}, - {file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"}, - {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"}, - {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"}, - {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"}, - {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"}, - {file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"}, - {file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"}, - {file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"}, - {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"}, - {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"}, - {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"}, - {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"}, - {file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"}, - {file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"}, - {file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"}, - {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"}, - {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"}, - {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"}, - {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"}, - {file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"}, - {file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"}, - {file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, + {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, + {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, + {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, + {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, + {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, + {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, + {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, + {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, ] [package.dependencies] From 2c65b12ef8f2a011e68e0a6b3879160bf76710d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:28:28 +0100 Subject: [PATCH 04/92] chore(deps-dev): bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 (#2847) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index ef30969aa9f..88c4fca6ee8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1484,13 +1484,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.28.0" -description = "Type annotations for boto3.DynamoDB 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.11" +description = "Type annotations for boto3.DynamoDB 1.28.11 service generated with mypy-boto3-builder 7.15.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.28.0.tar.gz", hash = "sha256:d12ed66edd7ded7089297b533d77e8b8ed8844da4e097cd912b61a08bfe4948b"}, - {file = "mypy_boto3_dynamodb-1.28.0-py3-none-any.whl", hash = "sha256:622f3d14dc1835a17ca511672d2f8fd08c03c4930f2845d06d1632b9f0c92aaf"}, + {file = "mypy-boto3-dynamodb-1.28.11.tar.gz", hash = "sha256:14b3fc0f091fad2c467733d410b1438b2747ab57292784abc0bc1adc3fa7ec60"}, + {file = "mypy_boto3_dynamodb-1.28.11-py3-none-any.whl", hash = "sha256:2b777cc080228e6c0e0b7a7e53b30d8c954637c7a5ec628f4397891f844ab0e8"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "4d7f3cf0fdeb0a018ce3f0ac0b39ec0f04894eab8367d3c05efbd3d02642e0f6" +content-hash = "29d35fd7c3d682f9c2952ea36e71e4e0ae1fca21018202e0e7f77f4d0662e5e4" diff --git a/pyproject.toml b/pyproject.toml index 0b3a84660e9..8570d73fc96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ pytest-benchmark = "^4.0.0" mypy-boto3-appconfig = "^1.28.0" mypy-boto3-cloudformation = "^1.28.10" mypy-boto3-cloudwatch = "^1.28.0" -mypy-boto3-dynamodb = "^1.28.0" +mypy-boto3-dynamodb = "^1.28.11" mypy-boto3-lambda = "^1.28.0" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.28.3" From a8aba58f3225724723c02c0e23403dcc280ccc6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:28:54 +0100 Subject: [PATCH 05/92] chore(deps): bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer (#2843) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 2 +- layer/scripts/layer-balancer/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index ce67f824a6c..9c9d131a573 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.19.0 github.com/aws/aws-sdk-go-v2/config v1.18.28 - github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1 + github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 38d0b70db29..65540590053 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -16,8 +16,8 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7n github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4= -github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1 h1:BRdW2JcxZSsen77Y0WoWIWY4+H9EXT55uEPWZKIcDHY= -github.com/aws/aws-sdk-go-v2/service/lambda v1.37.1/go.mod h1:zmdE2b9ZX8milexhZc3SeC3LwJRJpJ0k0fsuMBOSCEI= +github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0 h1:vgYsSbb7WICagS9pelgqG+CjPK2blsCMEqjTlU6RPEM= +github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0/go.mod h1:zmdE2b9ZX8milexhZc3SeC3LwJRJpJ0k0fsuMBOSCEI= github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k= github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= From 7f52fbf60897f75c600389f65989e66cc64a2f51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:31:02 +0100 Subject: [PATCH 06/92] chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer (#2844) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 6 +++--- layer/scripts/layer-balancer/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 9c9d131a573..d4cab54bf5f 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.19.0 - github.com/aws/aws-sdk-go-v2/config v1.18.28 + github.com/aws/aws-sdk-go-v2/config v1.18.29 github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 @@ -12,7 +12,7 @@ require ( require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.27 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.28 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect @@ -20,7 +20,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.20.0 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 65540590053..2208e8c0750 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -2,10 +2,10 @@ github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyD github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.18.28 h1:TINEaKyh1Td64tqFvn09iYpKiWjmHYrG1fa91q2gnqw= -github.com/aws/aws-sdk-go-v2/config v1.18.28/go.mod h1:nIL+4/8JdAuNHEjn/gPEXqtnS02Q3NXB/9Z7o5xE4+A= -github.com/aws/aws-sdk-go-v2/credentials v1.13.27 h1:dz0yr/yR1jweAnsCx+BmjerUILVPQ6FS5AwF/OyG1kA= -github.com/aws/aws-sdk-go-v2/credentials v1.13.27/go.mod h1:syOqAek45ZXZp29HlnRS/BNgMIW6uiRmeuQsz4Qh2UE= +github.com/aws/aws-sdk-go-v2/config v1.18.29 h1:yA+bSSRGhBwWuprG9I4VgxfK//NBLZ/0BGOHiV3f9oM= +github.com/aws/aws-sdk-go-v2/config v1.18.29/go.mod h1:bJT6P8A+KU1qvNMp8aj+/NmaI06Z670dHNoWsrLOgMg= +github.com/aws/aws-sdk-go-v2/credentials v1.13.28 h1:WM9tEHgoOh5ThJZ042UKnSx7TXGSC/bz63X3fsrQL2o= +github.com/aws/aws-sdk-go-v2/credentials v1.13.28/go.mod h1:86BSbSeamnVVdr1hPfBZVN8SXM7KxSAZAvhNxVfi8fU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= @@ -22,8 +22,8 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 h1:e5mnydVdCVWxP+5rPAGi2PYxC7u2OZgH1ypC114H04U= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.3/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY= +github.com/aws/aws-sdk-go-v2/service/sts v1.20.0 h1:jKmIOO+dFvCPuIhhM8u0Dy3dtd590n2kEDSYiGHoI98= +github.com/aws/aws-sdk-go-v2/service/sts v1.20.0/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From 37c3c62c6e4531df14b86e83c42e9c5e0814872c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:49:04 +0100 Subject: [PATCH 07/92] chore(deps-dev): bump mypy-boto3-lambda from 1.28.0 to 1.28.11 (#2845) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 88c4fca6ee8..cb45c697404 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1498,13 +1498,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-lambda" -version = "1.28.0" -description = "Type annotations for boto3.Lambda 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.11" +description = "Type annotations for boto3.Lambda 1.28.11 service generated with mypy-boto3-builder 7.15.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.28.0.tar.gz", hash = "sha256:a3abaf98e514f2cabed2cf0b1e77c94c81f0fbbba8a549b3c073577a9f9ac196"}, - {file = "mypy_boto3_lambda-1.28.0-py3-none-any.whl", hash = "sha256:5fd38df6418829b2f3a184918fc8ad1d49b6738509f1832cdc71f33588efbdfb"}, + {file = "mypy-boto3-lambda-1.28.11.tar.gz", hash = "sha256:2df51192be0ff1d37b3d34ffc8e5849e352e812c65fd79b1fa85c439367e478f"}, + {file = "mypy_boto3_lambda-1.28.11-py3-none-any.whl", hash = "sha256:8449b569b7cb387d2be3b8db584f60789f08fe61866d11f8b8d64b2431989a18"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "29d35fd7c3d682f9c2952ea36e71e4e0ae1fca21018202e0e7f77f4d0662e5e4" +content-hash = "fb6f2d9e404a3e567ab1093426addd4fd33aee51d2a692bc4f3d1399fb8f5ff3" diff --git a/pyproject.toml b/pyproject.toml index 8570d73fc96..5b085f6bb91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ mypy-boto3-appconfig = "^1.28.0" mypy-boto3-cloudformation = "^1.28.10" mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.28.11" -mypy-boto3-lambda = "^1.28.0" +mypy-boto3-lambda = "^1.28.11" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.28.3" mypy-boto3-ssm = "^1.28.0" From c9976a66df78b5d0ce08cdf856da1940c473d0f2 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 26 Jul 2023 09:16:47 +0100 Subject: [PATCH 08/92] docs(navigation): add nofollow attribute (#2842) --- docs/automation.md | 54 ++++++------- docs/core/event_handler/api_gateway.md | 47 +++++------ docs/core/event_handler/appsync.md | 18 ++--- docs/core/logger.md | 34 ++++---- docs/core/metrics.md | 29 +++---- docs/core/tracer.md | 22 +++--- docs/index.md | 104 ++++++++++++------------- docs/maintainers.md | 53 ++++++------- docs/roadmap.md | 22 +++--- docs/security.md | 6 +- docs/tutorial/index.md | 96 +++++++++++------------ docs/upgrade.md | 20 ++--- docs/utilities/batch.md | 24 +++--- docs/utilities/data_classes.md | 42 +++++----- docs/utilities/feature_flags.md | 28 +++---- docs/utilities/idempotency.md | 32 ++++---- docs/utilities/jmespath_functions.md | 14 ++-- docs/utilities/middleware_factory.md | 14 ++-- docs/utilities/parameters.md | 32 ++++---- docs/utilities/parser.md | 20 ++--- docs/utilities/streaming.md | 14 ++-- docs/utilities/typing.md | 4 +- docs/utilities/validation.md | 20 ++--- docs/we_made_this.md | 56 ++++++------- 24 files changed, 404 insertions(+), 401 deletions(-) diff --git a/docs/automation.md b/docs/automation.md index d0aacb89977..06b11525f9d 100644 --- a/docs/automation.md +++ b/docs/automation.md @@ -7,7 +7,7 @@ description: Automation practices and processes for Powertools for AWS Lambda (P ## Continuous integration practices -!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." +!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank" rel="nofollow"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank" rel="nofollow"}." Since all code changes require a pull request (PR) along with one or more reviewers, we automate quality and security checks **before**, **during**, and **after** a PR is merged to trunk (`develop`). @@ -21,7 +21,7 @@ This is a snapshot of our automated checks at a glance. ### Pre-commit checks -> [**Pre-commit configuration**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml){target="_blank"}. +> [**Pre-commit configuration**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml){target="_blank" rel="nofollow"}. Pre-commit checks are crucial for a fast feedback loop while ensuring security practices at the individual change level. @@ -29,13 +29,13 @@ To prevent scenarios where these checks are intentionally omitted at the client !!! note "These run locally only for changed files" -* [**Merge conflict check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L10){target="_blank"}. Checks for merge strings in each individual change accidentally left unresolved to prevent breakage. -* [**Code linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L22){target="_blank"}. Linter checks for industry quality standards and known bad practices that could lead to abuse. -* [**CloudFormation linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L34){target="_blank"}. `cfn-lint` ensures [best practices](https://github.com/aws-cloudformation/cfn-lint/blob/86f0370bd43b400ed4c485180dbc2697f73367b2/docs/rules.md){target=""_blank"} at our documentation examples. -* [**Markdown linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L25){target="_blank}. Primarily [industry markdown practices](https://github.com/DavidAnson/markdownlint/blob/d01180ec5a014083ee9d574b693a8d7fbc1e566d/README.md#rules--aliases){target="_blank"} at this stage. -* [**GitHub Actions linting**](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank"}. `actionlint` ensures workflows follow [GitHub Actions security practices](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}. It guards against numerous [leading practices](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank"} to prevent common configuration mistakes, insecure inline scripts, among many others. -* [**Terraform linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L43){target="_blank"}. As of now, largely formatting until we increase our Terraform coverage in documentation examples. -* [**Secrets linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/.pre-commit-config.yaml#L49){target="_blank"}. Detects industry credentials that might be accidentally leaked in source code. +* [**Merge conflict check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L10){target="_blank" rel="nofollow"}. Checks for merge strings in each individual change accidentally left unresolved to prevent breakage. +* [**Code linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L22){target="_blank" rel="nofollow"}. Linter checks for industry quality standards and known bad practices that could lead to abuse. +* [**CloudFormation linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L34){target="_blank" rel="nofollow"}. `cfn-lint` ensures [best practices](https://github.com/aws-cloudformation/cfn-lint/blob/86f0370bd43b400ed4c485180dbc2697f73367b2/docs/rules.md){target=""_blank"} at our documentation examples. +* [**Markdown linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L25){target="_blank}. Primarily [industry markdown practices](https://github.com/DavidAnson/markdownlint/blob/d01180ec5a014083ee9d574b693a8d7fbc1e566d/README.md#rules--aliases){target="_blank" rel="nofollow"} at this stage. +* [**GitHub Actions linting**](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank" rel="nofollow"}. `actionlint` ensures workflows follow [GitHub Actions security practices](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank" rel="nofollow"}. It guards against numerous [leading practices](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank" rel="nofollow"} to prevent common configuration mistakes, insecure inline scripts, among many others. +* [**Terraform linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L43){target="_blank" rel="nofollow"}. As of now, largely formatting until we increase our Terraform coverage in documentation examples. +* [**Secrets linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/.pre-commit-config.yaml#L49){target="_blank" rel="nofollow"}. Detects industry credentials that might be accidentally leaked in source code. ### Pre-Pull Request checks @@ -44,9 +44,9 @@ For an improved contributing experience, most of our checks can run locally. For !!! note "These are in addition to [pre-commit checks](#pre-commit-checks)." * [**Static typing analysis**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L108). `mypy` checks for static typing annotations to prevent common bugs in Python that may or may not lead to abuse. -* [**Tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L31){target="_blank"}. We run `unit`, `functional`, and `performance` tests ([_see our definition_](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank"}). Besides breaking changes, we are investing in mutation testing to find additional sources of bugs and potential abuse. -* [**Security baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank"}. `bandit` detects common security issues defined by Python Code Quality Authority (PyCQA). -* [**Complexity baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L79){target="_blank"}. We run a series of maintenability and cyclomatic checks to reduce code and logic complexity. This aids reviewers' cognitive overhead and long-term maintainers revisiting legacy code at a later date. +* [**Tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L31){target="_blank" rel="nofollow"}. We run `unit`, `functional`, and `performance` tests ([_see our definition_](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank" rel="nofollow"}). Besides breaking changes, we are investing in mutation testing to find additional sources of bugs and potential abuse. +* [**Security baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank" rel="nofollow"}. `bandit` detects common security issues defined by Python Code Quality Authority (PyCQA). +* [**Complexity baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L79){target="_blank" rel="nofollow"}. We run a series of maintenability and cyclomatic checks to reduce code and logic complexity. This aids reviewers' cognitive overhead and long-term maintainers revisiting legacy code at a later date. ### Pull Request checks @@ -54,13 +54,13 @@ While we trust contributors and maintainers do go through pre-commit and pre-pul !!! note "Checks described earlier are omitted to improve reading experience." -* [**Semantic PR title**](https://github.com/Ezard/semantic-prs){target="_blank"}. We enforce PR titles follow semantic naming, for example `chore(category): change`. This benefits contributors with a lower entry bar, no need for semantic commits. It also benefits everyone looking for an [useful changelog message](https://docs.powertools.aws.dev/lambda/python/latest/changelog/){target="_blank"} on **what** changed and **where**. -* [**Related issue check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L44){target="_blank"}. [Every change require an issue](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#contributing-via-pull-requests){target="_blank"} describing its needs. This enforces a PR has a related issue by blocking merge operations if missing. -* [**Acknowledgment check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L63){target="_blank"}. [Ensures PR template](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/PULL_REQUEST_TEMPLATE.md#L36){target="_blank"} is used and every contributor is aware of code redistribution. -* [**Code coverage diff**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/quality_check.yml#L73){target="_blank"}. Educates contributors and maintainers about code coverage differences for a given change. -* [**Contribution size check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_label_added.yml#L44){target="_blank"}. Suggests contributors and maintainers to break up large changes (100-499 LOC) in smaller PRs. It helps reduce overlooking security and other practices due to increased cognitive overhead. -* [**Dependency vulnerability check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/dependency-review.yml#L22){target="_blank"}. Verifies any dependency changes for common vulnerability exposures (CVEs), in addition to our daily check on any dependencies used (e.g., Python, Docker, Go, etc.) -* [**GitHub Actions security check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/secure_workflows.yml#L35){target="_blank"}. Enforces use of immutable 3rd-party GitHub Actions (_e.g., `actions/checkout@_`) to prevent abuse. Upgrades are handled by a [separate automated process](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/dependabot.yml#L4){target="_blank"} that includes a maintainer review to also prevent unexpected behavior changes. +* [**Semantic PR title**](https://github.com/Ezard/semantic-prs){target="_blank" rel="nofollow"}. We enforce PR titles follow semantic naming, for example `chore(category): change`. This benefits contributors with a lower entry bar, no need for semantic commits. It also benefits everyone looking for an [useful changelog message](https://docs.powertools.aws.dev/lambda/python/latest/changelog/){target="_blank" rel="nofollow"} on **what** changed and **where**. +* [**Related issue check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L44){target="_blank" rel="nofollow"}. [Every change require an issue](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#contributing-via-pull-requests){target="_blank" rel="nofollow"} describing its needs. This enforces a PR has a related issue by blocking merge operations if missing. +* [**Acknowledgment check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L63){target="_blank" rel="nofollow"}. [Ensures PR template](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/PULL_REQUEST_TEMPLATE.md#L36){target="_blank" rel="nofollow"} is used and every contributor is aware of code redistribution. +* [**Code coverage diff**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/quality_check.yml#L73){target="_blank" rel="nofollow"}. Educates contributors and maintainers about code coverage differences for a given change. +* [**Contribution size check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_label_added.yml#L44){target="_blank" rel="nofollow"}. Suggests contributors and maintainers to break up large changes (100-499 LOC) in smaller PRs. It helps reduce overlooking security and other practices due to increased cognitive overhead. +* [**Dependency vulnerability check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/dependency-review.yml#L22){target="_blank" rel="nofollow"}. Verifies any dependency changes for common vulnerability exposures (CVEs), in addition to our daily check on any dependencies used (e.g., Python, Docker, Go, etc.) +* [**GitHub Actions security check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/secure_workflows.yml#L35){target="_blank" rel="nofollow"}. Enforces use of immutable 3rd-party GitHub Actions (_e.g., `actions/checkout@_`) to prevent abuse. Upgrades are handled by a [separate automated process](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/dependabot.yml#L4){target="_blank" rel="nofollow"} that includes a maintainer review to also prevent unexpected behavior changes. ### After merge checks @@ -68,18 +68,18 @@ While we trust contributors and maintainers do go through pre-commit and pre-pul We strike a balance in security and contribution experience. These automated checks take several minutes to complete. Failures are reviewed by a maintainer on-call and before a release. -* [**End-to-end tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/run-e2e-tests.yml#L41){target="_blank"}. We run E2E with a [high degree of parallelization](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#test-runner-parallelization). While it is designed to also run locally, it may incur AWS charges to contributors. For additional security, all infrastructure is ephemeral per change and per Python version. -* [**SAST check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/codeql-analysis.yml#L20){target="_blank"}. GitHub CodeQL runs ~30m static analysis in the entire codebase. -* [**Security posture check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/ossf_scorecard.yml#L14){target="_blank"}. OSSF Scorecard runs numerous automated checks upon changes, and raises security alerts if [OSSF security practices](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"} are no longer followed. -* [**Rebuild Changelog**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/build_changelog.yml#L23){target="_blank"}. We rebuild our entire changelog upon changes and create a PR for maintainers. This has the added benefit in keeping a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches){target="_blank"} while keeping removing error-prone tasks from maintainers. -* [**Stage documentation**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_push_docs.yml#L27C16-L27C16){target="_blank"}. We rebuild and deploy changes to the documentation to a [staged version](https://docs.powertools.aws.dev/lambda/python/stage/){target="_blank"}. This gives us safety that our docs can always be rebuilt, and ready to release to production when needed. -* [**Update draft release**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/release-drafter.yml#L25){target="_blank"}. We use [Release Drafter](https://github.com/release-drafter/release-drafter){target="_blank"} to generate a portion of our release notes and to always keep a fresh draft upon changes. You can read our [thoughts on a good quality release notes here](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#drafting-release-notes){target="_blank"} (human readable changes + automation). +* [**End-to-end tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/run-e2e-tests.yml#L41){target="_blank" rel="nofollow"}. We run E2E with a [high degree of parallelization](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#test-runner-parallelization). While it is designed to also run locally, it may incur AWS charges to contributors. For additional security, all infrastructure is ephemeral per change and per Python version. +* [**SAST check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/codeql-analysis.yml#L20){target="_blank" rel="nofollow"}. GitHub CodeQL runs ~30m static analysis in the entire codebase. +* [**Security posture check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/ossf_scorecard.yml#L14){target="_blank" rel="nofollow"}. OSSF Scorecard runs numerous automated checks upon changes, and raises security alerts if [OSSF security practices](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank" rel="nofollow"} are no longer followed. +* [**Rebuild Changelog**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/build_changelog.yml#L23){target="_blank" rel="nofollow"}. We rebuild our entire changelog upon changes and create a PR for maintainers. This has the added benefit in keeping a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches){target="_blank" rel="nofollow"} while keeping removing error-prone tasks from maintainers. +* [**Stage documentation**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_push_docs.yml#L27C16-L27C16){target="_blank" rel="nofollow"}. We rebuild and deploy changes to the documentation to a [staged version](https://docs.powertools.aws.dev/lambda/python/stage/){target="_blank" rel="nofollow"}. This gives us safety that our docs can always be rebuilt, and ready to release to production when needed. +* [**Update draft release**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/release-drafter.yml#L25){target="_blank" rel="nofollow"}. We use [Release Drafter](https://github.com/release-drafter/release-drafter){target="_blank" rel="nofollow"} to generate a portion of our release notes and to always keep a fresh draft upon changes. You can read our [thoughts on a good quality release notes here](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#drafting-release-notes){target="_blank" rel="nofollow"} (human readable changes + automation). ## Continuous deployment practices -!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank"}." +!!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank" rel="nofollow"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank" rel="nofollow"}." -Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. +Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank" rel="nofollow"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. We use a combination of provenance and signed attestation for our builds, source code sealing, SAST scanners, Python specific static code analysis, ephemeral credentials that last a given job step, and more. diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 0e9c050ff4c..720432dd3c1 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -9,18 +9,19 @@ Event handler for Amazon API Gateway REST and HTTP APIs, Application Loader Bala * Lightweight routing to reduce boilerplate for API Gateway REST/HTTP API, ALB and Lambda Function URLs. * Support for CORS, binary and Gzip compression, Decimals JSON encoding and bring your own JSON serializer -* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"} for self-documented event schema +* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank" rel="nofollow"} for self-documented event schema ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. ### Required resources -If you're using any API Gateway integration, you must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank"} configured to invoke your Lambda function. + +If you're using any API Gateway integration, you must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank" rel="nofollow"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank" rel="nofollow"} configured to invoke your Lambda function. -In case of using [VPC Lattice](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"}, you must have a service network configured to invoke your Lambda function. +In case of using [VPC Lattice](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank" rel="nofollow"}, you must have a service network configured to invoke your Lambda function. This is the sample infrastructure for API Gateway and Lambda Function URLs we are using for the examples in this documentation. @@ -104,7 +105,7 @@ When using Amazon Application Load Balancer (ALB) to front your Lambda functions #### Lambda Function URL -When using [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html){target="_blank"}, you can use `LambdaFunctionUrlResolver`. +When using [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html){target="_blank" rel="nofollow"}, you can use `LambdaFunctionUrlResolver`. === "getting_started_lambda_function_url_resolver.py" @@ -120,7 +121,7 @@ When using [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/d #### VPC Lattice -When using [VPC Lattice with AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"}, you can use `VPCLatticeResolver`. +When using [VPC Lattice with AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank" rel="nofollow"}, you can use `VPCLatticeResolver`. === "getting_started_vpclattice_resolver.py" @@ -163,7 +164,7 @@ Each dynamic route you set must be part of your function signature. This allows ???+ note We recommend having explicit routes whenever possible; use catch-all routes sparingly. -You can use a [regex](https://docs.python.org/3/library/re.html#regular-expression-syntax){target="_blank"} string to handle an arbitrary number of paths within a request, for example `.+`. +You can use a [regex](https://docs.python.org/3/library/re.html#regular-expression-syntax){target="_blank" rel="nofollow"} string to handle an arbitrary number of paths within a request, for example `.+`. You can also combine nested paths with greedy regex to catch in between routes. @@ -209,7 +210,7 @@ If you need to accept multiple HTTP methods in a single function, you can use th ### Accessing request details -Event Handler integrates with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"}, and it exposes their respective resolver request details and convenient methods under `app.current_event`. +Event Handler integrates with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank" rel="nofollow"}, and it exposes their respective resolver request details and convenient methods under `app.current_event`. That is why you see `app.resolve(event, context)` in every example. This allows Event Handler to resolve requests, and expose data like `app.lambda_context` and `app.current_event`. @@ -267,11 +268,11 @@ We provide pre-defined errors for the most popular ones such as HTTP 400, 401, 4 ### Custom Domain API Mappings -When using [Custom Domain API Mappings feature](https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html){target="_blank"}, you must use **`strip_prefixes`** param in the `APIGatewayRestResolver` constructor. +When using [Custom Domain API Mappings feature](https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html){target="_blank" rel="nofollow"}, you must use **`strip_prefixes`** param in the `APIGatewayRestResolver` constructor. **Scenario**: You have a custom domain `api.mydomain.dev`. Then you set `/payment` API Mapping to forward any payment requests to your Payments API. -**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/aws-powertools/powertools-lambda-roadmap/issues/34){target="_blank"}. +**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/aws-powertools/powertools-lambda-roadmap/issues/34){target="_blank" rel="nofollow"}. To address this API Gateway behavior, we use `strip_prefixes` parameter to account for these prefixes that are now injected into the path regardless of which type of API Gateway you're using. @@ -346,12 +347,12 @@ For convenience, these are the default values when using `CORSConfig` to enable | Key | Value | Note | | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **[allow_origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin){target="_blank"}**: `str` | `*` | Only use the default value for development. **Never use `*` for production** unless your use case requires it | -| **[extra_origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin){target="_blank"}**: `List[str]` | `[]` | Additional origins to be allowed, in addition to the one specified in `allow_origin` | -| **[allow_headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers){target="_blank"}**: `List[str]` | `[Authorization, Content-Type, X-Amz-Date, X-Api-Key, X-Amz-Security-Token]` | Additional headers will be appended to the default list for your convenience | -| **[expose_headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers){target="_blank"}**: `List[str]` | `[]` | Any additional header beyond the [safe listed by CORS specification](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header){target="_blank"}. | -| **[max_age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age){target="_blank"}**: `int` | `` | Only for pre-flight requests if you choose to have your function to handle it instead of API Gateway | -| **[allow_credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials){target="_blank"}**: `bool` | `False` | Only necessary when you need to expose cookies, authorization headers or TLS client certificates. | +| **[allow_origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin){target="_blank" rel="nofollow"}**: `str` | `*` | Only use the default value for development. **Never use `*` for production** unless your use case requires it | +| **[extra_origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin){target="_blank" rel="nofollow"}**: `List[str]` | `[]` | Additional origins to be allowed, in addition to the one specified in `allow_origin` | +| **[allow_headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers){target="_blank" rel="nofollow"}**: `List[str]` | `[Authorization, Content-Type, X-Amz-Date, X-Api-Key, X-Amz-Security-Token]` | Additional headers will be appended to the default list for your convenience | +| **[expose_headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers){target="_blank" rel="nofollow"}**: `List[str]` | `[]` | Any additional header beyond the [safe listed by CORS specification](https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header){target="_blank" rel="nofollow"}. | +| **[max_age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age){target="_blank" rel="nofollow"}**: `int` | `` | Only for pre-flight requests if you choose to have your function to handle it instead of API Gateway | +| **[allow_credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials){target="_blank" rel="nofollow"}**: `bool` | `False` | Only necessary when you need to expose cookies, authorization headers or TLS client certificates. | ### Fine grained responses @@ -362,7 +363,7 @@ You can use the `Response` class to have full control over the response. For exa Some event sources require headers and cookies to be encoded as `multiValueHeaders`. ???+ warning "Using multiple values for HTTP headers in ALB?" - Make sure you [enable the multi value headers feature](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers){target="_blank"} to serialize response headers correctly. + Make sure you [enable the multi value headers feature](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers){target="_blank" rel="nofollow"} to serialize response headers correctly. === "fine_grained_responses.py" @@ -447,7 +448,7 @@ Like `compress` feature, the client must send the `Accept` header with the corre ### Debug mode -You can enable debug mode via `debug` param, or via `POWERTOOLS_DEV` [environment variable](../../index.md#environment-variables){target="_blank"}. +You can enable debug mode via `debug` param, or via `POWERTOOLS_DEV` [environment variable](../../index.md#environment-variables){target="_blank" rel="nofollow"}. This will enable full tracebacks errors in the response, print request and responses, and set CORS in development mode. @@ -601,7 +602,7 @@ _**Benefits**_ _**Downsides**_ -* **Cold starts**. Frequent deployments and/or high load can diminish the benefit of monolithic functions depending on your latency requirements, due to [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank"}. Always load test to pragmatically balance between your customer experience and development cognitive load. +* **Cold starts**. Frequent deployments and/or high load can diminish the benefit of monolithic functions depending on your latency requirements, due to [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank" rel="nofollow"}. Always load test to pragmatically balance between your customer experience and development cognitive load. * **Granular security permissions**. The micro function approach enables you to use fine-grained permissions & access controls, separate external dependencies & code signing at the function level. Conversely, you could have multiple functions while duplicating the final code artifact in a monolithic approach. * Regardless, least privilege can be applied to either approaches. * **Higher risk per deployment**. A misconfiguration or invalid import can cause disruption if not caught earlier in automated testing. Multiple functions can mitigate misconfigurations but they would still share the same code artifact. You can further minimize risks with multiple environments in your CI/CD pipeline. @@ -614,13 +615,13 @@ A micro function means that your final code artifact will be different to each f **Benefits** -* **Granular scaling**. A micro function can benefit from the [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank"} to scale differently depending on each part of your application. Concurrency controls and provisioned concurrency can also be used at a granular level for capacity management. +* **Granular scaling**. A micro function can benefit from the [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank" rel="nofollow"} to scale differently depending on each part of your application. Concurrency controls and provisioned concurrency can also be used at a granular level for capacity management. * **Discoverability**. Micro functions are easier do visualize when using distributed tracing. Their high-level architectures can be self-explanatory, and complexity is highly visible — assuming each function is named to the business purpose it serves. -* **Package size**. An independent function can be significant smaller (KB vs MB) depending on external dependencies it require to perform its purpose. Conversely, a monolithic approach can benefit from [Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html){target="_blank"} to optimize builds for external dependencies. +* **Package size**. An independent function can be significant smaller (KB vs MB) depending on external dependencies it require to perform its purpose. Conversely, a monolithic approach can benefit from [Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html){target="_blank" rel="nofollow"} to optimize builds for external dependencies. **Downsides** -* **Upfront investment**. You need custom build tooling to bundle assets, including [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank"}. Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes. +* **Upfront investment**. You need custom build tooling to bundle assets, including [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank" rel="nofollow"}. Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes. * Engineering discipline is necessary for both approaches. Micro-function approach however requires further attention in consistency as the number of functions grow, just like any distributed system. * **Harder to share code**. Shared code must be carefully evaluated to avoid unnecessary deployments when that changes. Equally, if shared code isn't a library, your development, building, deployment tooling need to accommodate the distinct layout. @@ -693,7 +694,7 @@ You can test your routes by passing a proxy event request with required params. Chalice is a full featured microframework that manages application and infrastructure. This utility, however, is largely focused on routing to reduce boilerplate and expects you to setup and manage infrastructure with your framework of choice. -That said, [Chalice has native integration with Lambda Powertools](https://aws.github.io/chalice/topics/middleware.html){target="_blank"} if you're looking for a more opinionated and web framework feature set. +That said, [Chalice has native integration with Lambda Powertools](https://aws.github.io/chalice/topics/middleware.html){target="_blank" rel="nofollow"} if you're looking for a more opinionated and web framework feature set. **What happened to `ApiGatewayResolver`?** diff --git a/docs/core/event_handler/appsync.md b/docs/core/event_handler/appsync.md index 789bf788004..b0f8a294ebd 100644 --- a/docs/core/event_handler/appsync.md +++ b/docs/core/event_handler/appsync.md @@ -9,15 +9,15 @@ Event handler for AWS AppSync Direct Lambda Resolver and Amplify GraphQL Transfo * Automatically parse API arguments to function arguments * Choose between strictly match a GraphQL field name or all of them to a function -* Integrates with [Data classes utilities](../../utilities/data_classes.md){target="_blank"} to access resolver and identity information +* Integrates with [Data classes utilities](../../utilities/data_classes.md){target="_blank" rel="nofollow"} to access resolver and identity information * Works with both Direct Lambda Resolver and Amplify GraphQL Transformer `@function` directive * Support async Python 3.8+ functions, and generators ## Terminology -**[Direct Lambda Resolver](https://docs.aws.amazon.com/appsync/latest/devguide/direct-lambda-reference.html){target="_blank"}**. A custom AppSync Resolver to bypass the use of Apache Velocity Template (VTL) and automatically map your function's response to a GraphQL field. +**[Direct Lambda Resolver](https://docs.aws.amazon.com/appsync/latest/devguide/direct-lambda-reference.html){target="_blank" rel="nofollow"}**. A custom AppSync Resolver to bypass the use of Apache Velocity Template (VTL) and automatically map your function's response to a GraphQL field. -**[Amplify GraphQL Transformer](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank"}**. Custom GraphQL directives to define your application's data model using Schema Definition Language (SDL). Amplify CLI uses these directives to convert GraphQL SDL into full descriptive AWS CloudFormation templates. +**[Amplify GraphQL Transformer](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank" rel="nofollow"}**. Custom GraphQL directives to define your application's data model using Schema Definition Language (SDL). Amplify CLI uses these directives to convert GraphQL SDL into full descriptive AWS CloudFormation templates. ## Getting started @@ -28,7 +28,7 @@ You must have an existing AppSync GraphQL API and IAM permissions to invoke your This is the sample infrastructure we are using for the initial examples with a AppSync Direct Lambda Resolver. ???+ tip "Tip: Designing GraphQL Schemas for the first time?" - Visit [AWS AppSync schema documentation](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html){target="_blank"} for understanding how to define types, nesting, and pagination. + Visit [AWS AppSync schema documentation](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html){target="_blank" rel="nofollow"} for understanding how to define types, nesting, and pagination. === "getting_started_schema.graphql" @@ -93,7 +93,7 @@ Here's an example with two separate functions to resolve `getTodo` and `listTodo ### Scalar functions -When working with [AWS AppSync Scalar types](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html){target="_blank"}, you might want to generate the same values for data validation purposes. +When working with [AWS AppSync Scalar types](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html){target="_blank" rel="nofollow"}, you might want to generate the same values for data validation purposes. For convenience, the most commonly used values are available as functions within `scalar_types_utils` module. @@ -143,7 +143,7 @@ For Lambda Python3.8+ runtime, this utility supports async functions when you us ### Amplify GraphQL Transformer -Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/install){target="_blank"}, create a new API using `amplify add api` and use the following GraphQL Schema. +Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/install){target="_blank" rel="nofollow"}, create a new API using `amplify add api` and use the following GraphQL Schema. @@ -151,7 +151,7 @@ Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/ins --8<-- "examples/event_handler_graphql/src/amplify_graphql_transformer_schema.graphql" ``` -[Create two new basic Python functions](https://docs.amplify.aws/cli/function#set-up-a-function){target="_blank"} via `amplify add function`. +[Create two new basic Python functions](https://docs.amplify.aws/cli/function#set-up-a-function){target="_blank" rel="nofollow"} via `amplify add function`. ???+ note Amplify CLI generated functions use `Pipenv` as a dependency manager. Your function source code is located at **`amplify/backend/function/your-function-name`**. @@ -192,7 +192,7 @@ Use the following code for `merchantInfo` and `searchMerchant` functions respect ### Custom data models -You can subclass [AppSyncResolverEvent](../../utilities/data_classes.md#appsync-resolver){target="_blank"} to bring your own set of methods to handle incoming events, by using `data_model` param in the `resolve` method. +You can subclass [AppSyncResolverEvent](../../utilities/data_classes.md#appsync-resolver){target="_blank" rel="nofollow"} to bring your own set of methods to handle incoming events, by using `data_model` param in the `resolve` method. === "custom_models.py.py" @@ -215,7 +215,7 @@ You can subclass [AppSyncResolverEvent](../../utilities/data_classes.md#appsync- ### Split operations with Router ???+ tip - Read the **[considerations section for trade-offs between monolithic and micro functions](./api_gateway.md#considerations){target="_blank"}**, as it's also applicable here. + Read the **[considerations section for trade-offs between monolithic and micro functions](./api_gateway.md#considerations){target="_blank" rel="nofollow"}**, as it's also applicable here. As you grow the number of related GraphQL operations a given Lambda function should handle, it is natural to split them into separate files to ease maintenance - That's when the `Router` feature comes handy. diff --git a/docs/core/logger.md b/docs/core/logger.md index 94aa1a71a6b..20accabb310 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -15,7 +15,7 @@ Logger provides an opinionated logger with output structured as JSON. ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. Logger requires two settings: @@ -39,7 +39,7 @@ Your Logger will include the following keys to your structured logging: | **message**: `Any` | `Collecting payment` | Unserializable JSON values are casted as `str` | | **timestamp**: `str` | `2021-05-03 10:20:19,650+0200` | Timestamp with milliseconds, by default uses local timezone | | **service**: `str` | `payment` | Service name defined, by default `service_undefined` | -| **xray_trace_id**: `str` | `1-5759e988-bd862e3fe1be46a994272793` | When [tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"}, it shows X-Ray Trace ID | +| **xray_trace_id**: `str` | `1-5759e988-bd862e3fe1be46a994272793` | When [tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank" rel="nofollow"}, it shows X-Ray Trace ID | | **sampling_rate**: `float` | `0.1` | When enabled, it shows sampling rate in percentage e.g. 10% | | **exception_name**: `str` | `ValueError` | When `logger.exception` is used and there is an exception | | **exception**: `str` | `Traceback (most recent call last)..` | When `logger.exception` is used and there is an exception | @@ -83,7 +83,7 @@ When debugging in non-production environments, you can instruct Logger to log th ### Setting a Correlation ID -You can set a Correlation ID using `correlation_id_path` param by passing a [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank"}. +You can set a Correlation ID using `correlation_id_path` param by passing a [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank" rel="nofollow"}. ???+ tip You can retrieve correlation IDs via `get_correlation_id` method @@ -108,7 +108,7 @@ You can set a Correlation ID using `correlation_id_path` param by passing a [JME #### set_correlation_id method -You can also use `set_correlation_id` method to inject it anywhere else in your code. Example below uses [Event Source Data Classes utility](../utilities/data_classes.md){target="_blank"} to easily access events properties. +You can also use `set_correlation_id` method to inject it anywhere else in your code. Example below uses [Event Source Data Classes utility](../utilities/data_classes.md){target="_blank" rel="nofollow"} to easily access events properties. === "set_correlation_id_method.py" @@ -163,7 +163,7 @@ You can append additional keys using either mechanism: #### append_keys method ???+ warning - `append_keys` is not thread-safe, please see [RFC](https://github.com/aws-powertools/powertools-lambda-python/issues/991){target="_blank"}. + `append_keys` is not thread-safe, please see [RFC](https://github.com/aws-powertools/powertools-lambda-python/issues/991){target="_blank" rel="nofollow"}. You can append your own keys to your existing Logger via `append_keys(**additional_key_values)` method. @@ -242,7 +242,7 @@ You can remove any additional key from Logger state using `remove_keys`. #### Clearing all 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 `clear_state=True` param in `inject_lambda_context` decorator. +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" rel="nofollow"}, this means that custom keys can be persisted across invocations. If you want all custom keys to be deleted, you can use `clear_state=True` param in `inject_lambda_context` decorator. ???+ tip "Tip: When is this useful?" It is useful when you add multiple custom keys conditionally, instead of setting a default `None` value if not present. Any key with `None` value is automatically removed by Logger. @@ -301,7 +301,7 @@ Logger can optionally log uncaught exceptions by setting `log_uncaught_exception ??? question "What are uncaught exceptions?" - It's any raised exception that wasn't handled by the [`except` statement](https://docs.python.org/3.9/tutorial/errors.html#handling-exceptions){target="_blank"}, leading a Python program to a non-successful exit. + It's any raised exception that wasn't handled by the [`except` statement](https://docs.python.org/3.9/tutorial/errors.html#handling-exceptions){target="_blank" rel="nofollow"}, leading a Python program to a non-successful exit. They are typically raised intentionally to signal a problem (`raise ValueError`), or a propagated exception from elsewhere in your code that you didn't handle it willingly or not (`KeyError`, `jsonDecoderError`, etc.). @@ -323,10 +323,10 @@ Logger uses Python's standard logging date format with the addition of timezone: You can easily change the date format using one of the following parameters: -* **`datefmt`**. You can pass any [strftime format codes](https://strftime.org/){target="_blank"}. Use `%F` if you need milliseconds. +* **`datefmt`**. You can pass any [strftime format codes](https://strftime.org/){target="_blank" rel="nofollow"}. Use `%F` if you need milliseconds. * **`use_rfc3339`**. This flag will use a format compliant with both RFC3339 and ISO8601: `2022-10-27T16:27:43.738+02:00` -???+ tip "Prefer using [datetime string formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes){target="_blank"}?" +???+ tip "Prefer using [datetime string formats](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes){target="_blank" rel="nofollow"}?" Use `use_datetime_directive` flag along with `datefmt` to instruct Logger to use `datetime` instead of `time.strftime`. === "date_formatting.py" @@ -360,7 +360,7 @@ You can use any of the following built-in JMESPath expressions as part of [injec ### Reusing Logger across your code -Similar to [Tracer](./tracer.md#reusing-tracer-across-your-code){target="_blank"}, a new instance that uses the same `service` name - env var or explicit parameter - will reuse a previous Logger instance. Just like `logging.getLogger("logger_name")` would in the standard library if called with the same logger name. +Similar to [Tracer](./tracer.md#reusing-tracer-across-your-code){target="_blank" rel="nofollow"}, a new instance that uses the same `service` name - env var or explicit parameter - will reuse a previous Logger instance. Just like `logging.getLogger("logger_name")` would in the standard library if called with the same logger name. Notice in the CloudWatch Logs output how `payment_id` appeared as expected when logging in `collect.py`. @@ -407,7 +407,7 @@ You can use values ranging from `0.0` to `1` (100%) when setting `POWERTOOLS_LOG Sampling decision happens at the Logger initialization. This means sampling may happen significantly more or less than depending on your traffic patterns, for example a steady low number of invocations and thus few cold starts. ???+ note - Open a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank"} if you want Logger to calculate sampling for every invocation + Open a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank" rel="nofollow"} if you want Logger to calculate sampling for every invocation === "sampling_debug_logs.py" @@ -447,9 +447,9 @@ If you prefer configuring it separately, or you'd want to bring this JSON Format ### Observability providers -!!! note "In this context, an observability provider is an [AWS Lambda Partner](https://go.aws/3HtU6CZ){target="_blank"} offering a platform for logging, metrics, traces, etc." +!!! note "In this context, an observability provider is an [AWS Lambda Partner](https://go.aws/3HtU6CZ){target="_blank" rel="nofollow"} offering a platform for logging, metrics, traces, etc." -You can send logs to the observability provider of your choice via [Lambda Extensions](https://aws.amazon.com/blogs/compute/using-aws-lambda-extensions-to-send-logs-to-custom-destinations/){target="_blank"}. In most cases, you shouldn't need any custom Logger configuration, and logs will be shipped async without any performance impact. +You can send logs to the observability provider of your choice via [Lambda Extensions](https://aws.amazon.com/blogs/compute/using-aws-lambda-extensions-to-send-logs-to-custom-destinations/){target="_blank" rel="nofollow"}. In most cases, you shouldn't need any custom Logger configuration, and logs will be shipped async without any performance impact. #### Built-in formatters @@ -634,7 +634,7 @@ For exceptional cases where you want to completely replace our formatter logic, #### Bring your own JSON serializer -By default, Logger uses `json.dumps` and `json.loads` as serializer and deserializer respectively. There could be scenarios where you are making use of alternative JSON libraries like [orjson](https://github.com/ijl/orjson){target="_blank"}. +By default, Logger uses `json.dumps` and `json.loads` as serializer and deserializer respectively. There could be scenarios where you are making use of alternative JSON libraries like [orjson](https://github.com/ijl/orjson){target="_blank" rel="nofollow"}. As parameters don't always translate well between them, you can pass any callable that receives a `dict` and return a `str`: @@ -664,7 +664,7 @@ This is a Pytest sample that provides the minimum information necessary for Logg ``` ???+ tip - Check out the built-in [Pytest caplog fixture](https://docs.pytest.org/en/latest/how-to/logging.html){target="_blank"} to assert plain log messages + Check out the built-in [Pytest caplog fixture](https://docs.pytest.org/en/latest/how-to/logging.html){target="_blank" rel="nofollow"} to assert plain log messages ### Pytest live log feature @@ -703,7 +703,7 @@ By default all registered loggers will be modified. You can change this behavior ### How can I add standard library logging attributes to a log record? -The Python standard library log records contains a [large set of attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes){target="_blank"}, however only a few are included in Powertools for AWS Lambda (Python) Logger log record by default. +The Python standard library log records contains a [large set of attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes){target="_blank" rel="nofollow"}, however only a few are included in Powertools for AWS Lambda (Python) Logger log record by default. You can include any of these logging attributes as key value arguments (`kwargs`) when instantiating `Logger` or `LambdaPowertoolsFormatter`. @@ -744,4 +744,4 @@ Here's an example where we persist `payment_id` not `request_id`. Note that `pay ### How do I aggregate and search Powertools for AWS Lambda (Python) logs across accounts? -As of now, ElasticSearch (ELK) or 3rd party solutions are best suited to this task. Please refer to this [discussion for more details](https://github.com/aws-powertools/powertools-lambda-python/issues/460){target="_blank"} +As of now, ElasticSearch (ELK) or 3rd party solutions are best suited to this task. Please refer to this [discussion for more details](https://github.com/aws-powertools/powertools-lambda-python/issues/460){target="_blank" rel="nofollow"} diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 052406300dc..289068aeeeb 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -3,9 +3,9 @@ title: Metrics description: Core utility --- -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){target="_blank"}. +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){target="_blank" rel="nofollow"}. -These metrics can be visualized through [Amazon CloudWatch Console](https://console.aws.amazon.com/cloudwatch/){target="_blank"}. +These metrics can be visualized through [Amazon CloudWatch Console](https://console.aws.amazon.com/cloudwatch/){target="_blank" rel="nofollow"}. ## Key features @@ -22,7 +22,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar * **Dimensions**. Metrics metadata in key-value format. They help you slice and dice metrics visualization, for example `ColdStart` metric by Payment `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 [here](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics){target="_blank"}. +* **Resolution**. It's a value representing the storage resolution for the corresponding metric. Metrics can be either Standard or High resolution. Read more [here](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics){target="_blank" rel="nofollow"}.
@@ -32,7 +32,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. Metric has two global settings that will be used across all metrics emitted: @@ -83,7 +83,7 @@ You can create metrics using `add_metric`, and you can create dimensions for all ### Adding high-resolution metrics -You can create [high-resolution metrics](https://aws.amazon.com/about-aws/whats-new/2023/02/amazon-cloudwatch-high-resolution-metric-extraction-structured-logs/){target="_blank"} passing `resolution` parameter to `add_metric`. +You can create [high-resolution metrics](https://aws.amazon.com/about-aws/whats-new/2023/02/amazon-cloudwatch-high-resolution-metric-extraction-structured-logs/){target="_blank" rel="nofollow"} passing `resolution` parameter to `add_metric`. ???+ tip "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. @@ -154,7 +154,7 @@ This decorator also **validates**, **serializes**, and **flushes** all your metr * Maximum of 29 user-defined dimensions * Namespace is set, and no more than one - * Metric units must be [supported by CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank"} + * Metric units must be [supported by CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank" rel="nofollow"} #### Raising SchemaValidationError on empty metrics @@ -191,7 +191,7 @@ If it's a cold start invocation, this feature will: This has the advantage of keeping cold start metric separate from your application metrics, where you might have unrelated dimensions. ???+ info - We do not emit 0 as a value for ColdStart metric for cost reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank"} if you'd prefer a flag to override it. + We do not emit 0 as a value for ColdStart metric for cost reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank" rel="nofollow"} if you'd prefer a flag to override it. ## Advanced @@ -219,7 +219,7 @@ You can add high-cardinality data as part of your Metrics log with `add_metadata CloudWatch EMF uses the same dimensions across all your metrics. Use `single_metric` if you have a metric that should have different dimensions. ???+ info - Generally, this would be an edge case since you [pay for unique metric](https://aws.amazon.com/cloudwatch/pricing){target="_blank"}. Keep the following formula in mind: + Generally, this would be an edge case since you [pay for unique metric](https://aws.amazon.com/cloudwatch/pricing){target="_blank" rel="nofollow"}. Keep the following formula in mind: **unique metric = (metric_name + dimension_name + dimension_value)** @@ -282,16 +282,17 @@ You can use `EphemeralMetrics` class when looking to isolate multiple instances !!! question "Why not changing the default `Metrics` behaviour to not share data across instances?" -This is an intentional design to prevent accidental data deduplication or data loss issues due to [CloudWatch EMF](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank"} metric dimension constraint. +This is an intentional design to prevent accidental data deduplication or data loss issues due to [CloudWatch EMF](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank" rel="nofollow"} metric dimension constraint. -In CloudWatch, there are two metric ingestion mechanisms: [EMF (async)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank"} and [`PutMetricData` API (sync)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data){target="_blank"}. + +In CloudWatch, there are two metric ingestion mechanisms: [EMF (async)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank" rel="nofollow"} and [`PutMetricData` API (sync)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data){target="_blank" rel="nofollow"}. The former creates metrics asynchronously via CloudWatch Logs, and the latter uses a synchronous and more flexible ingestion API. !!! important "Key concept" - CloudWatch [considers a metric unique](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Metric){target="_blank"} by a combination of metric **name**, metric **namespace**, and zero or more metric **dimensions**. + CloudWatch [considers a metric unique](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Metric){target="_blank" rel="nofollow"} by a combination of metric **name**, metric **namespace**, and zero or more metric **dimensions**. -With EMF, metric dimensions are shared with any metrics you define. With `PutMetricData` API, you can set a [list](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank"} defining one or more metrics with distinct dimensions. +With EMF, metric dimensions are shared with any metrics you define. With `PutMetricData` API, you can set a [list](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank" rel="nofollow"} defining one or more metrics with distinct dimensions. This is a subtle yet important distinction. Imagine you had the following metrics to emit: @@ -328,7 +329,7 @@ That is why `Metrics` shares data across instances by default, as that covers 80 For example, `Metrics(namespace="ServerlessAirline", service="booking")` -Make sure to set `POWERTOOLS_METRICS_NAMESPACE` and `POWERTOOLS_SERVICE_NAME` before running your tests to prevent failing on `SchemaValidation` exception. You can set it before you run tests or via pytest plugins like [dotenv](https://pypi.org/project/pytest-dotenv/){target="_blank"}. +Make sure to set `POWERTOOLS_METRICS_NAMESPACE` and `POWERTOOLS_SERVICE_NAME` before running your tests to prevent failing on `SchemaValidation` exception. You can set it before you run tests or via pytest plugins like [dotenv](https://pypi.org/project/pytest-dotenv/){target="_blank" rel="nofollow"}. ```bash title="Injecting dummy Metric Namespace before running tests" --8<-- "examples/metrics/src/run_tests_env_var.sh" @@ -373,4 +374,4 @@ You can read standard output and assert whether metrics have been flushed. Here' ``` ???+ tip - For more elaborate assertions and comparisons, check out [our functional testing for Metrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/test_metrics.py){target="_blank"} + For more elaborate assertions and comparisons, check out [our functional testing for Metrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/test_metrics.py){target="_blank" rel="nofollow"} diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 349a868dc83..6ffd44d3be0 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -3,7 +3,7 @@ title: Tracer description: Core utility --- -Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github.com/aws/aws-xray-sdk-python/){target="_blank"}. +Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github.com/aws/aws-xray-sdk-python/){target="_blank" rel="nofollow"}. ![Tracer showcase](../media/tracer_utility_showcase.png) @@ -17,19 +17,19 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github. ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. -!!! note "Tracer relies on AWS X-Ray SDK over [OpenTelememetry Distro (ADOT)](https://aws-otel.github.io/docs/getting-started/lambda){target="_blank"} for optimal cold start (lower latency)." +!!! note "Tracer relies on AWS X-Ray SDK over [OpenTelememetry Distro (ADOT)](https://aws-otel.github.io/docs/getting-started/lambda){target="_blank" rel="nofollow"} for optimal cold start (lower latency)." ### Install -!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank" rel="nofollow"}" Add `aws-lambda-powertools[tracer]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Tracer. ### Permissions -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){target="_blank"} to send traces to AWS X-Ray. +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){target="_blank" rel="nofollow"} to send traces to AWS X-Ray. ```yaml hl_lines="9 12" title="AWS Serverless Application Model (SAM) example" --8<-- "examples/tracer/sam/template.yaml" @@ -51,7 +51,7 @@ You can quickly start by initializing `Tracer` and use `capture_lambda_handler` ### Annotations & Metadata -**Annotations** are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to create [Trace Groups](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-xray-adds-the-ability-to-group-traces/){target="_blank"} to slice and dice your transactions. +**Annotations** are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to create [Trace Groups](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-xray-adds-the-ability-to-group-traces/){target="_blank" rel="nofollow"} to slice and dice your transactions. ```python hl_lines="8" title="Adding annotations with put_annotation method" --8<-- "examples/tracer/src/put_trace_annotations.py" @@ -107,7 +107,7 @@ You can trace asynchronous functions and generator functions (including context ### Patching modules -Tracer automatically patches all [supported libraries by X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-python-patching.html){target="_blank"} during initialization, by default. Underneath, AWS X-Ray SDK checks whether a supported library has been imported before patching. +Tracer automatically patches all [supported libraries by X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-python-patching.html){target="_blank" rel="nofollow"} during initialization, by default. Underneath, AWS X-Ray SDK checks whether a supported library has been imported before patching. If you're looking to shave a few microseconds, or milliseconds depending on your function memory configuration, you can patch specific modules using `patch_modules` param: @@ -162,7 +162,7 @@ You can use `ignore_endpoint` method with the hostname and/or URLs you'd like it ???+ info This snippet assumes you have aiohttp as a dependency -You can use `aiohttp_trace_config` function to create a valid [aiohttp trace_config object](https://docs.aiohttp.org/en/stable/tracing_reference.html){target="_blank"}. This is necessary since X-Ray utilizes [aiohttp](https://docs.aiohttp.org/en/stable/){target="_blank"} trace hooks to capture requests end-to-end. +You can use `aiohttp_trace_config` function to create a valid [aiohttp trace_config object](https://docs.aiohttp.org/en/stable/tracing_reference.html){target="_blank" rel="nofollow"}. This is necessary since X-Ray utilizes [aiohttp](https://docs.aiohttp.org/en/stable/){target="_blank" rel="nofollow"} trace hooks to capture requests end-to-end. ```python hl_lines="7 17" title="Tracing aiohttp requests" --8<-- "examples/tracer/src/tracing_aiohttp.py" @@ -172,7 +172,7 @@ You can use `aiohttp_trace_config` function to create a valid [aiohttp trace_con You can use `tracer.provider` attribute to access all methods provided by AWS X-Ray `xray_recorder` object. -This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example [thread-safe](https://github.com/aws/aws-xray-sdk-python/#user-content-trace-threadpoolexecutor){target="_blank"}, or [context managers](https://github.com/aws/aws-xray-sdk-python/#user-content-start-a-custom-segmentsubsegment){target="_blank"}. +This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example [thread-safe](https://github.com/aws/aws-xray-sdk-python/#user-content-trace-threadpoolexecutor){target="_blank" rel="nofollow"}, or [context managers](https://github.com/aws/aws-xray-sdk-python/#user-content-start-a-custom-segmentsubsegment){target="_blank" rel="nofollow"}. ```python hl_lines="14" title="Tracing a code block with in_subsegment escape hatch" --8<-- "examples/tracer/src/sdk_escape_hatch.py" @@ -181,7 +181,7 @@ This is useful when you need a feature available in X-Ray that is not available ### Concurrent asynchronous functions ???+ warning - [X-Ray SDK will raise an exception](https://github.com/aws/aws-xray-sdk-python/issues/164){target="_blank"} when async functions are run and traced concurrently + [X-Ray SDK will raise an exception](https://github.com/aws/aws-xray-sdk-python/issues/164){target="_blank" rel="nofollow"} when async functions are run and traced concurrently A safe workaround mechanism is to use `in_subsegment_async` available via Tracer escape hatch (`tracer.provider`). @@ -221,4 +221,4 @@ Tracer is disabled by default when not running in the AWS Lambda environment - T * Use annotations on key operations to slice and dice traces, create unique views, and create metrics from it via Trace Groups * Use a namespace when adding metadata to group data more easily -* Annotations and metadata are added to the current subsegment opened. If you want them in a specific subsegment, use a [context manager](https://github.com/aws/aws-xray-sdk-python/#start-a-custom-segmentsubsegment){target="_blank"} via the escape hatch mechanism +* Annotations and metadata are added to the current subsegment opened. If you want them in a specific subsegment, use a [context manager](https://github.com/aws/aws-xray-sdk-python/#start-a-custom-segmentsubsegment){target="_blank" rel="nofollow"} via the escape hatch mechanism diff --git a/docs/index.md b/docs/index.md index dff39e1e20b..e6d262f62e6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,15 +8,15 @@ description: Powertools for AWS Lambda (Python) Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity. ???+ tip - Powertools for AWS Lambda (Python) is also available for [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank"}, [TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} + Powertools for AWS Lambda (Python) is also available for [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank" rel="nofollow"}, [TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/){target="_blank" rel="nofollow"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank" rel="nofollow"} ??? hint "Support this project by becoming a reference customer, sharing your work, or using Layers/SAR :heart:" You can choose to support us in three ways: - 1) [**Become a reference customer**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank"}. This gives us permission to list your company in our documentation. + 1) [**Become a reference customer**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank" rel="nofollow"}. This gives us permission to list your company in our documentation. - 2) [**Share your work**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank"}. Blog posts, video, sample projects you used Powertools! + 2) [**Share your work**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank" rel="nofollow"}. Blog posts, video, sample projects you used Powertools! 3) Use [**Lambda Layers**](#lambda-layer) or [**SAR**](#sar), if possible. This helps us understand who uses Powertools for AWS Lambda (Python) in a non-intrusive way, and helps us gain future investments for other Powertools for AWS Lambda languages. @@ -33,7 +33,7 @@ You can install Powertools for AWS Lambda (Python) using one of the following op !!! question "Looking for Pip signed releases? [Learn more about verifying signed builds](./security.md#verifying-signed-builds)" ??? question "Using Pip? You might need to install additional dependencies." - [**Tracer**](./core/tracer.md){target="_blank"}, [**Validation**](./utilities/validation.md){target="_blank"} and [**Parser**](./utilities/parser.md){target="_blank"} require additional dependencies. If you prefer to install all of them, use [**`pip install "aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard:. + [**Tracer**](./core/tracer.md){target="_blank" rel="nofollow"}, [**Validation**](./utilities/validation.md){target="_blank" rel="nofollow"} and [**Parser**](./utilities/parser.md){target="_blank" rel="nofollow"} require additional dependencies. If you prefer to install all of them, use [**`pip install "aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard:. For example: @@ -46,7 +46,7 @@ You can install Powertools for AWS Lambda (Python) using one of the following op !!! info "Using Lambda Layer? Simply add [**`"aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard: as a development dependency." -Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank"}. This helps us achieve an optimal package size and initialization. However, when developing locally, you need to install AWS SDK as a development dependency (not as a production dependency): +Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank" rel="nofollow"}. This helps us achieve an optimal package size and initialization. However, when developing locally, you need to install AWS SDK as a development dependency (not as a production dependency): * **Pip**: [**`pip install "aws-lambda-powertools[aws-sdk]"`**](#){: .copyMe}:clipboard: * **Poetry**: [**`poetry add "aws-lambda-powertools[aws-sdk]" --group dev`**](#){: .copyMe}:clipboard: @@ -55,24 +55,24 @@ Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda ??? question "Why is that necessary?" Powertools for AWS Lambda (Python) relies on the AWS SDK being available to use in the target runtime (AWS Lambda). - As a result, it affects your favorite IDE in terms of code auto-completion, or running your tests suite locally with no Lambda emulation such as [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html){target="_blank"}. + As a result, it affects your favorite IDE in terms of code auto-completion, or running your tests suite locally with no Lambda emulation such as [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html){target="_blank" rel="nofollow"}. **A word about dependency resolution** In this context, `[aws-sdk]` is an alias to the `boto3` package. Due to dependency resolution, it'll either install: -* **(A)** the SDK version available in [Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank"} -* **(B)** a more up-to-date version if another package you use also depends on `boto3`, for example [Powertools for AWS Lambda (Python) Tracer](core/tracer.md){target="_blank"} +* **(A)** the SDK version available in [Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank" rel="nofollow"} +* **(B)** a more up-to-date version if another package you use also depends on `boto3`, for example [Powertools for AWS Lambda (Python) Tracer](core/tracer.md){target="_blank" rel="nofollow"} ### Lambda Layer ???+ warning "As of now, Container Image deployment (OCI) or inline Lambda functions do not support Lambda Layers." -[Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html){target="_blank"} is a .zip file archive that can contain additional code, pre-packaged dependencies, data, or configuration files. Layers promote code sharing and separation of responsibilities so that you can iterate faster on writing business logic. +[Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html){target="_blank" rel="nofollow"} is a .zip file archive that can contain additional code, pre-packaged dependencies, data, or configuration files. Layers promote code sharing and separation of responsibilities so that you can iterate faster on writing business logic. -For our Layers, we compile and optimize [all dependencies](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/pyproject.toml#L98){target="_blank"}, and [remove duplicate dependencies already available in the Lambda runtime](https://github.com/awslabs/cdk-aws-lambda-powertools-layer/blob/main/layer/Python/Dockerfile#L36){target="_blank"} to achieve the most optimal size. +For our Layers, we compile and optimize [all dependencies](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/pyproject.toml#L98){target="_blank" rel="nofollow"}, and [remove duplicate dependencies already available in the Lambda runtime](https://github.com/awslabs/cdk-aws-lambda-powertools-layer/blob/main/layer/Python/Dockerfile#L36){target="_blank" rel="nofollow"} to achieve the most optimal size. -You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambda Console](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-using){target="_blank"}, or your preferred deployment framework. +You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambda Console](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-using){target="_blank" rel="nofollow"}, or your preferred deployment framework. ??? note "Note: Click to expand and copy any regional Lambda Layer ARN" @@ -464,8 +464,8 @@ Compared with the [public Layer ARN](#lambda-layer) option, SAR allows you to ch | App | ARN | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | -| [aws-lambda-powertools-python-layer](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer){target="_blank"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). | -| [aws-lambda-powertools-python-layer-arm64](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer-arm64){target="_blank"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer-arm64](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). For arm64 functions. | +| [aws-lambda-powertools-python-layer](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer){target="_blank" rel="nofollow"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). | +| [aws-lambda-powertools-python-layer-arm64](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer-arm64){target="_blank" rel="nofollow"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer-arm64](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). For arm64 functions. | ??? note "Click to expand and copy SAR code snippets for popular frameworks" @@ -549,7 +549,7 @@ Compared with the [public Layer ARN](#lambda-layer) option, SAR allows you to ch === "Terraform" - > Credits to [Dani Comnea](https://github.com/DanyC97){target="_blank"} for providing the Terraform equivalent. + > Credits to [Dani Comnea](https://github.com/DanyC97){target="_blank" rel="nofollow"} for providing the Terraform equivalent. ```terraform hl_lines="12-13 15-20 23-25 40" terraform { @@ -597,7 +597,7 @@ Compared with the [public Layer ARN](#lambda-layer) option, SAR allows you to ch ??? example "Example: Least-privileged IAM permissions to deploy Layer" - > Credits to [mwarkentin](https://github.com/mwarkentin){target="_blank"} for providing the scoped down IAM permissions. + > Credits to [mwarkentin](https://github.com/mwarkentin){target="_blank" rel="nofollow"} for providing the scoped down IAM permissions. The region and the account id for `CloudFormationTransform` and `GetCfnTemplate` are fixed. @@ -681,21 +681,21 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai | Utility | Description | | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [**Tracing**](./core/tracer.md){target="_blank"} | Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions | -| [**Logger**](./core/logger.md){target="_blank"} | Structured logging made easier, and decorator to enrich structured logging with key Lambda context details | -| [**Metrics**](./core/metrics.md){target="_blank"} | Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF) | -| [**Event handler: AppSync**](./core/event_handler/appsync.md){target="_blank"} | AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function | +| [**Tracing**](./core/tracer.md){target="_blank" rel="nofollow"} | Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions | +| [**Logger**](./core/logger.md){target="_blank" rel="nofollow"} | Structured logging made easier, and decorator to enrich structured logging with key Lambda context details | +| [**Metrics**](./core/metrics.md){target="_blank" rel="nofollow"} | Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF) | +| [**Event handler: AppSync**](./core/event_handler/appsync.md){target="_blank" rel="nofollow"} | AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function | | [**Event handler: API Gateway, ALB and Lambda Function URL**](https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/) | Amazon API Gateway REST/HTTP API and ALB event handler for Lambda functions invoked using Proxy integration, and Lambda Function URL | -| [**Middleware factory**](./utilities/middleware_factory.md){target="_blank"} | Decorator factory to create your own middleware to run logic before, and after each Lambda invocation | -| [**Parameters**](./utilities/parameters.md){target="_blank"} | Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time | -| [**Batch processing**](./utilities/batch.md){target="_blank"} | Handle partial failures for AWS SQS batch processing | -| [**Typing**](./utilities/typing.md){target="_blank"} | Static typing classes to speedup development in your IDE | -| [**Validation**](./utilities/validation.md){target="_blank"} | JSON Schema validator for inbound events and responses | -| [**Event source data classes**](./utilities/data_classes.md){target="_blank"} | Data classes describing the schema of common Lambda event triggers | -| [**Parser**](./utilities/parser.md){target="_blank"} | Data parsing and deep validation using Pydantic | -| [**Idempotency**](./utilities/idempotency.md){target="_blank"} | Idempotent Lambda handler | -| [**Feature Flags**](./utilities/feature_flags.md){target="_blank"} | A simple rule engine to evaluate when one or multiple features should be enabled depending on the input | -| [**Streaming**](./utilities/streaming.md){target="_blank"} | Streams datasets larger than the available memory as streaming data. | +| [**Middleware factory**](./utilities/middleware_factory.md){target="_blank" rel="nofollow"} | Decorator factory to create your own middleware to run logic before, and after each Lambda invocation | +| [**Parameters**](./utilities/parameters.md){target="_blank" rel="nofollow"} | Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time | +| [**Batch processing**](./utilities/batch.md){target="_blank" rel="nofollow"} | Handle partial failures for AWS SQS batch processing | +| [**Typing**](./utilities/typing.md){target="_blank" rel="nofollow"} | Static typing classes to speedup development in your IDE | +| [**Validation**](./utilities/validation.md){target="_blank" rel="nofollow"} | JSON Schema validator for inbound events and responses | +| [**Event source data classes**](./utilities/data_classes.md){target="_blank" rel="nofollow"} | Data classes describing the schema of common Lambda event triggers | +| [**Parser**](./utilities/parser.md){target="_blank" rel="nofollow"} | Data parsing and deep validation using Pydantic | +| [**Idempotency**](./utilities/idempotency.md){target="_blank" rel="nofollow"} | Idempotent Lambda handler | +| [**Feature Flags**](./utilities/feature_flags.md){target="_blank" rel="nofollow"} | A simple rule engine to evaluate when one or multiple features should be enabled depending on the input | +| [**Streaming**](./utilities/streaming.md){target="_blank" rel="nofollow"} | Streams datasets larger than the available memory as streaming data. | ## Environment variables @@ -705,18 +705,18 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai | Environment variable | Description | Utility | Default | | ----------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------- | | **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | `"service_undefined"` | -| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics){target="_blank"} | `None` | -| **POWERTOOLS_TRACE_DISABLED** | Explicitly disables tracing | [Tracing](./core/tracer){target="_blank"} | `false` | -| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer){target="_blank"} | `true` | -| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer){target="_blank"} | `true` | -| **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory){target="_blank"} | `false` | -| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger){target="_blank"} | `false` | -| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger){target="_blank"} | `0` | -| **POWERTOOLS_LOG_DEDUPLICATION_DISABLED** | Disables log deduplication filter protection to use Pytest Live Log feature | [Logging](./core/logger){target="_blank"} | `false` | -| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](./utilities/parameters/#adjusting-cache-ttl){target="_blank"} | `5` | -| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters/#ssmprovider){target="_blank"} | `false` | +| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics){target="_blank" rel="nofollow"} | `None` | +| **POWERTOOLS_TRACE_DISABLED** | Explicitly disables tracing | [Tracing](./core/tracer){target="_blank" rel="nofollow"} | `false` | +| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer){target="_blank" rel="nofollow"} | `true` | +| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer){target="_blank" rel="nofollow"} | `true` | +| **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory){target="_blank" rel="nofollow"} | `false` | +| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger){target="_blank" rel="nofollow"} | `false` | +| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger){target="_blank" rel="nofollow"} | `0` | +| **POWERTOOLS_LOG_DEDUPLICATION_DISABLED** | Disables log deduplication filter protection to use Pytest Live Log feature | [Logging](./core/logger){target="_blank" rel="nofollow"} | `false` | +| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](./utilities/parameters/#adjusting-cache-ttl){target="_blank" rel="nofollow"} | `5` | +| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters/#ssmprovider){target="_blank" rel="nofollow"} | `false` | | **POWERTOOLS_DEV** | Increases verbosity across utilities | Multiple; see [POWERTOOLS_DEV effect below](#optimizing-for-non-production-environments) | `false` | -| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger){target="_blank"} | `INFO` | +| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger){target="_blank" rel="nofollow"} | `INFO` | ### Optimizing for non-production environments @@ -743,24 +743,24 @@ When necessary, you can use `POWERTOOLS_DEBUG` environment variable to enable de ### 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 (Python), you can request to have your name and logo added to the README file by raising a [Support Powertools for AWS Lambda (Python) (become a reference)](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank"} 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 (Python), you can request to have your name and logo added to the README file by raising a [Support Powertools for AWS Lambda (Python) (become a reference)](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank" rel="nofollow"} issue. The following companies, among others, use Powertools: -* [Capital One](https://www.capitalone.com/){target="_blank"} -* [CPQi (Exadel Financial Services)](https://cpqi.com/){target="_blank"} -* [CloudZero](https://www.cloudzero.com/){target="_blank"} -* [CyberArk](https://www.cyberark.com/){target="_blank"} -* [globaldatanet](https://globaldatanet.com/){target="_blank"} -* [IMS](https://ims.tech/){target="_blank"} -* [Jit Security](https://www.jit.io/){target="_blank"} -* [Propellor.ai](https://www.propellor.ai/){target="_blank"} -* [TopSport](https://www.topsport.com.au/){target="_blank"} -* [Trek10](https://www.trek10.com/){target="_blank"} +* [Capital One](https://www.capitalone.com/){target="_blank" rel="nofollow"} +* [CPQi (Exadel Financial Services)](https://cpqi.com/){target="_blank" rel="nofollow"} +* [CloudZero](https://www.cloudzero.com/){target="_blank" rel="nofollow"} +* [CyberArk](https://www.cyberark.com/){target="_blank" rel="nofollow"} +* [globaldatanet](https://globaldatanet.com/){target="_blank" rel="nofollow"} +* [IMS](https://ims.tech/){target="_blank" rel="nofollow"} +* [Jit Security](https://www.jit.io/){target="_blank" rel="nofollow"} +* [Propellor.ai](https://www.propellor.ai/){target="_blank" rel="nofollow"} +* [TopSport](https://www.topsport.com.au/){target="_blank" rel="nofollow"} +* [Trek10](https://www.trek10.com/){target="_blank" rel="nofollow"} ### Sharing your work -Share what you did with Powertools for AWS Lambda (Python) 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools for AWS Lambda (Python) [here](https://docs.powertools.aws.dev/lambda/python/latest/we_made_this/){target="_blank"}. +Share what you did with Powertools for AWS Lambda (Python) 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools for AWS Lambda (Python) [here](https://docs.powertools.aws.dev/lambda/python/latest/we_made_this/){target="_blank" rel="nofollow"}. ### Using Lambda Layer or SAR diff --git a/docs/maintainers.md b/docs/maintainers.md index 6fc00c83cd9..061acbb4c8f 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -9,27 +9,27 @@ description: Playbook for active maintainers in Powertools for AWS Lambda (Pytho !!! note "Please treat this content as a living document." -This is document explains who the maintainers are, their responsibilities, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). +This is document explains who the maintainers are, their responsibilities, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CONTRIBUTING.md){target="_blank" rel="nofollow"}. ## Current Maintainers -| Maintainer | GitHub ID | Affiliation | -| ----------------- | ------------------------------------------------------- | ----------- | -| Heitor Lessa | [heitorlessa](https://github.com/heitorlessa) | Amazon | -| Simon Thulbourn | [sthulb](https://github.com/sthulb) | Amazon | -| Ruben Fonseca | [rubenfonseca](https://github.com/rubenfonseca) | Amazon | -| Leandro Damascena | [leandrodamascena](https://github.com/leandrodamascena) | Amazon | +| Maintainer | GitHub ID | Affiliation | +| ----------------- | --------------------------------------------------------------------------------------- | ----------- | +| Heitor Lessa | [heitorlessa](https://github.com/heitorlessa){target="_blank" rel="nofollow"} | Amazon | +| Simon Thulbourn | [sthulb](https://github.com/sthulb){target="_blank" rel="nofollow"} | Amazon | +| Ruben Fonseca | [rubenfonseca](https://github.com/rubenfonseca){target="_blank" rel="nofollow"} | Amazon | +| Leandro Damascena | [leandrodamascena](https://github.com/leandrodamascena){target="_blank" rel="nofollow"} | Amazon | ## Emeritus Previous active maintainers who contributed to this project. -| Maintainer | GitHub ID | Affiliation | -| ----------------- | ----------------------------------------------- | ----------- | -| Tom McCarthy | [cakepietoast](https://github.com/cakepietoast) | MongoDB | -| Nicolas Moutschen | [nmoutschen](https://github.com/nmoutschen) | Apollo | -| Alexander Melnyk | [am29d](https://github.com/am29d) | Amazon | -| Michal Ploski | [mploski](https://github.com/mploski) | Amazon | +| Maintainer | GitHub ID | Affiliation | +| ----------------- | ------------------------------------------------------------------------------- | ----------- | +| Tom McCarthy | [cakepietoast](https://github.com/cakepietoast){target="_blank" rel="nofollow"} | MongoDB | +| Nicolas Moutschen | [nmoutschen](https://github.com/nmoutschen){target="_blank" rel="nofollow"} | Apollo | +| Alexander Melnyk | [am29d](https://github.com/am29d){target="_blank" rel="nofollow"} | Amazon | +| Michal Ploski | [mploski](https://github.com/mploski){target="_blank" rel="nofollow"} | Amazon | ## Labels @@ -74,13 +74,14 @@ These are the most common labels used by maintainers to triage issues, pull requ ## Maintainer Responsibilities -Maintainers are active and visible members of the community, and have [maintain-level permissions on a repository](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization). Use those privileges to serve the community and evolve code as follows. +Maintainers are active and visible members of the community, and have [maintain-level permissions on a repository](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization){target="_blank" rel="nofollow"}. Use those privileges to serve the community and evolve code as follows. Be aware of recurring ambiguous situations and [document them](#common-scenarios) to help your fellow maintainers. ### Uphold Code of Conduct -Model the behavior set forward by the [Code of Conduct](CODE_OF_CONDUCT.md) and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate behavior does not immediately fall within the [Code of Conduct](CODE_OF_CONDUCT.md). + +Model the behavior set forward by the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank" rel="nofollow"} and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate behavior does not immediately fall within the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank" rel="nofollow"}. These might be nuanced and should be handled with extra care - when in doubt, do not engage and reach out to other maintainers and admins. @@ -88,7 +89,7 @@ These might be nuanced and should be handled with extra care - when in doubt, do Security is your number one priority. Maintainer's Github keys must be password protected securely and any reported security vulnerabilities are addressed before features or bugs. -Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](SECURITY.md) for details. +Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/SECURITY.md){target="_blank" rel="nofollow"} for details. ### Review Pull Requests @@ -96,7 +97,7 @@ Review pull requests regularly, comment, suggest, reject, merge and close. Accep PRs are [labeled](#labels) based on file changes and semantic title. Pay attention to whether labels reflect the current state of the PR and correct accordingly. -Use and enforce [semantic versioning](https://semver.org/) pull request titles, as these will be used for [CHANGELOG](CHANGELOG.md) and [Release notes](https://github.com/aws-powertools/powertools-lambda-python/releases) - make sure they communicate their intent at the human level. +Use and enforce [semantic versioning](https://semver.org/) pull request titles, as these will be used for [CHANGELOG](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CHANGELOG.md){target="_blank" rel="nofollow"} and [Release notes](https://github.com/aws-powertools/powertools-lambda-python/releases) - make sure they communicate their intent at the human level. > TODO: This is an area we want to automate using the new GitHub GraphQL API. @@ -287,14 +288,14 @@ Ensure the repo highlights features that should be elevated to the project roadm Add integration checks that validate pull requests and pushes to ease the burden on Pull Request reviewers. Continuously revisit areas of improvement to reduce operational burden in all parties involved. ### Negative Impact on the Project - -Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](CODE_OF_CONDUCT.md) violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. + +Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank" rel="nofollow"} violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. ### Becoming a maintainer In 2023, we will revisit this. We need to improve our understanding of how other projects are doing, their mechanisms to promote key contributors, and how they interact daily. -We suspect this process might look similar to the [OpenSearch project](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md#becoming-a-maintainer). +We suspect this process might look similar to the [OpenSearch project](https://github.com/opensearch-project/.github/blob/main/MAINTAINERS.md#becoming-a-maintainer){target="_blank" rel="nofollow"}. ## Common scenarios @@ -314,7 +315,7 @@ When in doubt, use `need-more-information` or `need-customer-feedback` labels to ### Crediting contributions -We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-python/releases) as an automated process. If you find contributors are missing from the release note you're producing, please add them manually. +We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-python/releases){target="_blank" rel="nofollow"} as an automated process. If you find contributors are missing from the release note you're producing, please add them manually. ### Is that a bug? @@ -338,7 +339,7 @@ In the rare cases where both parties don't have the bandwidth or expertise to co ### Structure -Our E2E framework relies on [Pytest fixtures](https://docs.pytest.org/en/6.2.x/fixture.html) to coordinate infrastructure and test parallelization - see [Test Parallelization](#test-runner-parallelization) and [CDK CLI Parallelization](#cdk-cli-parallelization). +Our E2E framework relies on [Pytest fixtures](https://docs.pytest.org/en/6.2.x/fixture.html){target="_blank" rel="nofollow"} to coordinate infrastructure and test parallelization - see [Test Parallelization](#test-runner-parallelization) and [CDK CLI Parallelization](#cdk-cli-parallelization). **tests/e2e structure** @@ -387,7 +388,7 @@ Where: ### Mechanics -Under [`BaseInfrastructure`](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/e2e/utils/infrastructure.py), we hide the complexity of deployment and delete coordination under `deploy`, `delete`, and `create_lambda_functions` methods. +Under [`BaseInfrastructure`](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/e2e/utils/infrastructure.py){target="_blank" rel="nofollow"}, we hide the complexity of deployment and delete coordination under `deploy`, `delete`, and `create_lambda_functions` methods. This allows us to benefit from test and deployment parallelization, use IDE step-through debugging for a single test, run one, subset, or all tests and only deploy their related infrastructure, without any custom configuration. @@ -589,7 +590,7 @@ graph TD #### CDK CLI parallelization -For CDK CLI to work with [independent CDK Apps](https://docs.aws.amazon.com/cdk/v2/guide/apps.html), we specify an output directory when synthesizing our stack and deploy from said output directory. +For CDK CLI to work with [independent CDK Apps](https://docs.aws.amazon.com/cdk/v2/guide/apps.html){target="_blank" rel="nofollow"}, we specify an output directory when synthesizing our stack and deploy from said output directory. ```mermaid flowchart TD @@ -657,6 +658,6 @@ Where: - **`layer_build`**. Contains our Lambda Layer source code built once, used by all stacks independently - **`layer_build.diff`**. Contains a hash on whether our source code has changed to speed up further deployments and E2E tests -Together, all of this allows us to use Pytest like we would for any project, use CDK CLI and its [context methods](https://docs.aws.amazon.com/cdk/v2/guide/context.html#context_methods) (`from_lookup`), and use step-through debugging for a single E2E test without any extra configuration. +Together, all of this allows us to use Pytest like we would for any project, use CDK CLI and its [context methods](https://docs.aws.amazon.com/cdk/v2/guide/context.html#context_methods){target="_blank" rel="nofollow"} (`from_lookup`), and use step-through debugging for a single E2E test without any extra configuration. -> NOTE: VSCode doesn't support debugging processes spawning sub-processes (like CDK CLI does w/ shell and CDK App). Maybe [this works](https://stackoverflow.com/a/65339352). PyCharm works just fine. +> NOTE: VSCode doesn't support debugging processes spawning sub-processes (like CDK CLI does w/ shell and CDK App). Maybe [this works](https://stackoverflow.com/a/65339352){target="_blank" rel="nofollow"}. PyCharm works just fine. diff --git a/docs/roadmap.md b/docs/roadmap.md index 5e9515b9252..f432c2c56f7 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -4,13 +4,13 @@ This is our public roadmap that outlines the high level direction we are working towards, namely [Themes](#themes). We update this document when our priorities change: security and stability is our top priority. -[See our latest list of activities »](https://github.com/orgs/awslabs/projects/51/views/1?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"} +[See our latest list of activities »](https://github.com/orgs/awslabs/projects/51/views/1?query=is%3Aopen+sort%3Aupdated-desc){target="_blank" rel="nofollow"} ## Themes !!! info "Operational Excellence is priority number 1." -Themes are key activities maintainers are focusing on, besides bug reports. These are updated periodically and you can find the latest [under Epics in our public board](https://github.com/orgs/awslabs/projects/51/views/11?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"}. +Themes are key activities maintainers are focusing on, besides bug reports. These are updated periodically and you can find the latest [under Epics in our public board](https://github.com/orgs/awslabs/projects/51/views/11?query=is%3Aopen+sort%3Aupdated-desc){target="_blank" rel="nofollow"}. ### Increased end-to-end coverage @@ -20,7 +20,7 @@ Some Lambda Event Sources require clusters (e.g., MSK) leading to additional del ### Observability providers -We want to extend Tracer, Metrics, and Logger to support any [observability provider](https://github.com/aws-powertools/powertools-lambda-python/issues/1433){target="_blank"}. We need a RFC to define a contract and to identify two most requested observability providers that we can work with as an initial step. +We want to extend Tracer, Metrics, and Logger to support any [observability provider](https://github.com/aws-powertools/powertools-lambda-python/issues/1433){target="_blank" rel="nofollow"}. We need a RFC to define a contract and to identify two most requested observability providers that we can work with as an initial step. ### Lambda Layer in release notes @@ -34,15 +34,15 @@ This means we have room to include a JSON map for Lambda Layers and facilitate a We want to enable MyPy strict mode against the code base. We need a RFC to identify most critical areas to start, and do so gradually as to not impact new features and enhancements in parallel. -This also means bringing `typing-extensions` as a runtime dependency to ensure complete coverage across all Python versions. Future wise, we might be able to experiment with [MyPyC](https://github.com/mypyc/mypyc){target="_blank"} to compile less performing parts of the code base as a C-Extension. +This also means bringing `typing-extensions` as a runtime dependency to ensure complete coverage across all Python versions. Future wise, we might be able to experiment with [MyPyC](https://github.com/mypyc/mypyc){target="_blank" rel="nofollow"} to compile less performing parts of the code base as a C-Extension. ### New utilities -With V2 launched, we want to resume working on new utilities, specifically but not limited to the most commonly asked: **(1)** [Sensitive Data Masking](https://github.com/aws-powertools/powertools-lambda-python/issues/1173){target="_blank"}, **(2)** [Integration/End-to-end Testing](https://github.com/aws-powertools/powertools-lambda-python/issues/1169){target="_blank"}, and **(3)** [Event Bridge](https://github.com/aws-powertools/powertools-lambda-python/issues/1168){target="_blank"}. +With V2 launched, we want to resume working on new utilities, specifically but not limited to the most commonly asked: **(1)** [Sensitive Data Masking](https://github.com/aws-powertools/powertools-lambda-python/issues/1173){target="_blank" rel="nofollow"}, **(2)** [Integration/End-to-end Testing](https://github.com/aws-powertools/powertools-lambda-python/issues/1169){target="_blank" rel="nofollow"}, and **(3)** [Event Bridge](https://github.com/aws-powertools/powertools-lambda-python/issues/1168){target="_blank" rel="nofollow"}. ### Open iteration planning -We want to experiment running a bi-weekly audio channel on [Discord](https://discord.gg/B8zZKbbyET){target="_blank"} to help us prioritize backlog in real-time. Depending on attendance, we might switch to run an office hours instead. +We want to experiment running a bi-weekly audio channel on [Discord](https://discord.gg/B8zZKbbyET){target="_blank" rel="nofollow"} to help us prioritize backlog in real-time. Depending on attendance, we might switch to run an office hours instead. ## Roadmap status definition @@ -54,7 +54,7 @@ graph LR Visual representation -Within our [public board](https://github.com/orgs/awslabs/projects/51/views/1?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"}, you'll see the following values in the `Status` column: +Within our [public board](https://github.com/orgs/awslabs/projects/51/views/1?query=is%3Aopen+sort%3Aupdated-desc){target="_blank" rel="nofollow"}, 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. @@ -82,14 +82,14 @@ graph LR Our end-to-end mechanism follows four major steps: -* **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&template=feature_request.yml&title=Feature+request%3A+TITLE){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 issue template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE){target="_blank"} to describe its implementation, challenges, developer experience, dependencies, and alternative solutions. +* **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&template=feature_request.yml&title=Feature+request%3A+TITLE){target="_blank" rel="nofollow"} 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" rel="nofollow"}, customers reaction (👍), and use cases. +* **Request-for-comments (RFC)**. Design proposals use our [RFC issue template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE){target="_blank" rel="nofollow"} 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](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md){target="_blank"} document to understand how we triage issues and pull requests, labels and governance." +???+ info "See [Maintainers](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md){target="_blank" rel="nofollow"} document to understand how we triage issues and pull requests, labels and governance." ## Disclaimer diff --git a/docs/security.md b/docs/security.md index b3475e2c0c0..4572f921573 100644 --- a/docs/security.md +++ b/docs/security.md @@ -19,7 +19,7 @@ This page describes our security processes and supply chain practices. ### Verifying signed builds -!!! note "Starting from v2.20.0 releases, builds are [reproducible](https://slsa.dev/spec/v0.1/faq#q-what-about-reproducible-builds){target="_blank"} and signed publicly." +!!! note "Starting from v2.20.0 releases, builds are [reproducible](https://slsa.dev/spec/v0.1/faq#q-what-about-reproducible-builds){target="_blank" rel="nofollow"} and signed publicly."
![SLSA Supply Chain Threats](https://slsa.dev/images/v1.0/supply-chain-threats.svg) @@ -29,7 +29,7 @@ This page describes our security processes and supply chain practices. #### Terminology -We use [SLSA](https://slsa.dev/spec/v1.0/about){target="_blank"} to ensure our builds are reproducible and to adhere to [supply chain security practices](https://slsa.dev/spec/v1.0/threats-overview). +We use [SLSA](https://slsa.dev/spec/v1.0/about){target="_blank" rel="nofollow"} to ensure our builds are reproducible and to adhere to [supply chain security practices](https://slsa.dev/spec/v1.0/threats-overview). Within our [releases page](https://github.com/aws-powertools/powertools-lambda-python/releases), you will notice a new metadata file: `multiple.intoto.jsonl`. It's metadata to describe **where**, **when**, and **how** our build artifacts were produced - or simply, **attestation** in SLSA terminology. @@ -79,7 +79,7 @@ You can do this manually or automated via a shell script. We maintain the latter 5. **Runs SLSA Verifier against attestation**, GitHub Source, and release binary 6. **Cleanup** by removing downloaded files to keep your current directory tidy - ??? info "Expand or [click here](https://github.com/heitorlessa/aws-lambda-powertools-python/blob/refactor/ci-seal/.github/actions/verify-provenance/verify_provenance.sh#L95){target="_blank"} to see the script source code" + ??? info "Expand or [click here](https://github.com/heitorlessa/aws-lambda-powertools-python/blob/refactor/ci-seal/.github/actions/verify-provenance/verify_provenance.sh#L95){target="_blank" rel="nofollow"} to see the script source code" ```bash title=".github/actions/verify-provenance/verify_provenance.sh" ---8<-- ".github/actions/verify-provenance/verify_provenance.sh" diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index 6674b5bcf4e..b0aca95dd12 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -9,8 +9,8 @@ This tutorial progressively introduces Powertools for AWS Lambda (Python) core u ## Requirements -* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html){target="_blank"} and [configured with your credentials](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-set-up-credentials.html){target="_blank"}. -* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html){target="_blank"} installed. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html){target="_blank" rel="nofollow"} and [configured with your credentials](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-set-up-credentials.html){target="_blank" rel="nofollow"}. +* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html){target="_blank" rel="nofollow"} installed. ## Getting started @@ -87,7 +87,7 @@ Our Lambda code consists of an entry point function named `lambda_handler`, and When API Gateway receives a HTTP GET request on `/hello` route, Lambda will call our `lambda_handler` function, subsequently calling the `hello` function. API Gateway will use this response to return the correct HTTP Status Code and payload back to the caller. ???+ warning - For simplicity, we do not set up authentication and authorization! You can find more information on how to implement it on [AWS SAM documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-controlling-access-to-apis.html){target="_blank"}. + For simplicity, we do not set up authentication and authorization! You can find more information on how to implement it on [AWS SAM documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-controlling-access-to-apis.html){target="_blank" rel="nofollow"}. ### Run your code @@ -103,7 +103,7 @@ AWS SAM allows you to execute a serverless application locally by running `sam b 2021-11-26 17:43:08 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit) ``` -As a result, a local API endpoint will be exposed and you can invoke it using your browser, or your preferred HTTP API client e.g., [Postman](https://www.postman.com/downloads/){target="_blank"}, [httpie](https://httpie.io/){target="_blank"}, etc. +As a result, a local API endpoint will be exposed and you can invoke it using your browser, or your preferred HTTP API client e.g., [Postman](https://www.postman.com/downloads/){target="_blank" rel="nofollow"}, [httpie](https://httpie.io/){target="_blank" rel="nofollow"}, etc. ```bash title="Invoking our function locally via curl" > curl http://127.0.0.1:3000/hello @@ -111,7 +111,7 @@ As a result, a local API endpoint will be exposed and you can invoke it using yo ``` ???+ info - To learn more about local testing, please visit the [AWS SAM CLI local testing](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html){target="_blank"} documentation. + To learn more about local testing, please visit the [AWS SAM CLI local testing](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html){target="_blank" rel="nofollow"} documentation. #### Live test @@ -147,7 +147,7 @@ At the end of the deployment, you will find the API endpoint URL within `Outputs ``` ???+ Info - For more details on AWS SAM deployment mechanism, see [SAM Deploy reference docs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html){target="_blank"}. + For more details on AWS SAM deployment mechanism, see [SAM Deploy reference docs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html){target="_blank" rel="nofollow"}. ## Routing @@ -226,7 +226,7 @@ For this to work, we could create a new Lambda function to handle incoming reque We could group similar routes and intents, separate read and write operations resulting in fewer functions. It doesn't address the boilerplate routing code, but maybe it will be easier to add additional URLs. ???+ info "Info: You might be already asking yourself about mono vs micro-functions" - If you want a more detailed explanation of these two approaches, head over to the [trade-offs on each approach](../core/event_handler/api_gateway/#considerations){target="_blank"} later. + If you want a more detailed explanation of these two approaches, head over to the [trade-offs on each approach](../core/event_handler/api_gateway/#considerations){target="_blank" rel="nofollow"} later. A first attempt at the routing logic might look similar to the following code snippet. @@ -318,10 +318,10 @@ However, it forces us to understand the internal structure of the API Gateway re ### Simplifying with Event Handler -We can massively simplify cross-cutting concerns while keeping it lightweight by using [Event Handler](../core/event_handler/api_gateway.md){target="_blank"}. +We can massively simplify cross-cutting concerns while keeping it lightweight by using [Event Handler](../core/event_handler/api_gateway.md){target="_blank" rel="nofollow"}. ???+ tip - This is available for both [REST API (API Gateway, ALB)](../core/event_handler/api_gateway.md){target="_blank"} and [GraphQL API (AppSync)](../core/event_handler/appsync.md){target="_blank"}. + This is available for both [REST API (API Gateway, ALB)](../core/event_handler/api_gateway.md){target="_blank" rel="nofollow"} and [GraphQL API (AppSync)](../core/event_handler/appsync.md){target="_blank" rel="nofollow"}. Let's include Powertools for AWS Lambda (Python) as a dependency in `requirement.txt`, and use Event Handler to refactor our previous example. @@ -355,22 +355,22 @@ Let's include Powertools for AWS Lambda (Python) as a dependency in `requirement Use `sam build && sam local start-api` and try run it locally again. ???+ note - If you're coming from [Flask](https://flask.palletsprojects.com/en/2.0.x/){target="_blank"}, you will be familiar with this experience already. [Event Handler for API Gateway](../core/event_handler/api_gateway.md){target="_blank"} uses `APIGatewayRestResolver` to give a Flask-like experience while staying true to our tenet `Keep it lean`. + If you're coming from [Flask](https://flask.palletsprojects.com/en/2.0.x/){target="_blank" rel="nofollow"}, you will be familiar with this experience already. [Event Handler for API Gateway](../core/event_handler/api_gateway.md){target="_blank" rel="nofollow"} uses `APIGatewayRestResolver` to give a Flask-like experience while staying true to our tenet `Keep it lean`. We have added the route annotation as the decorator for our methods. It enables us to use the parameters passed in the request directly, and our responses are simply dictionaries. Lastly, we used `return app.resolve(event, context)` so Event Handler can resolve routes, inject the current request, handle serialization, route validation, etc. -From here, we could handle [404 routes](../core/event_handler/api_gateway.md#handling-not-found-routes){target="_blank"}, [error handling](../core/event_handler/api_gateway.md#exception-handling){target="_blank"}, [access query strings, payload](../core/event_handler/api_gateway.md#accessing-request-details){target="_blank"}, etc. +From here, we could handle [404 routes](../core/event_handler/api_gateway.md#handling-not-found-routes){target="_blank" rel="nofollow"}, [error handling](../core/event_handler/api_gateway.md#exception-handling){target="_blank" rel="nofollow"}, [access query strings, payload](../core/event_handler/api_gateway.md#accessing-request-details){target="_blank" rel="nofollow"}, etc. ???+ tip - If you'd like to learn how python decorators work under the hood, you can follow [Real Python](https://realpython.com/primer-on-python-decorators/){target="_blank"}'s article. + If you'd like to learn how python decorators work under the hood, you can follow [Real Python](https://realpython.com/primer-on-python-decorators/){target="_blank" rel="nofollow"}'s article. ## Structured Logging Over time, you realize that searching logs as text results in poor observability, it's hard to create metrics from, enumerate common exceptions, etc. -Then, you decided to propose production quality logging capabilities to your Lambda code. You found out that by having logs as `JSON` you can [structure them](https://docs.aws.amazon.com/lambda/latest/operatorguide/parse-logs.html){target="_blank"}, so that you can use any Log Analytics tool out there to quickly analyze them. +Then, you decided to propose production quality logging capabilities to your Lambda code. You found out that by having logs as `JSON` you can [structure them](https://docs.aws.amazon.com/lambda/latest/operatorguide/parse-logs.html){target="_blank" rel="nofollow"}, so that you can use any Log Analytics tool out there to quickly analyze them. This helps not only in searching, but produces consistent logs containing enough context and data to ask arbitrary questions on the status of your system. We can take advantage of CloudWatch Logs and Cloudwatch Insight for this purpose. @@ -454,7 +454,7 @@ We could start by creating a dictionary with Lambda context information or somet ???+ question "Surely this could be easier, right?" Yes! Powertools for AWS Lambda (Python) Logger to the rescue :-) -As we already have Powertools for AWS Lambda (Python) as a dependency, we can simply import [Logger](../core/logger.md){target="_blank"}. +As we already have Powertools for AWS Lambda (Python) as a dependency, we can simply import [Logger](../core/logger.md){target="_blank" rel="nofollow"}. ```python title="Refactoring with Powertools for AWS Lambda (Python) Logger" hl_lines="1 3 5 12 18 22" from aws_lambda_powertools import Logger @@ -487,8 +487,8 @@ Let's break this down: * **L5**: We add Powertools for AWS Lambda (Python) Logger; the boilerplate is now done for you. By default, we set `INFO` as the logging level if `LOG_LEVEL` env var isn't set. * **L22**: We use `logger.inject_lambda_context` decorator to inject key information from Lambda context into every log. -* **L22**: We also instruct Logger to use the incoming API Gateway Request ID as a [correlation id](../core/logger.md##set_correlation_id-method){target="_blank"} automatically. -* **L22**: Since we're in dev, we also use `log_event=True` to automatically log each incoming request for debugging. This can be also set via [environment variables](./index.md#environment-variables){target="_blank"}. +* **L22**: We also instruct Logger to use the incoming API Gateway Request ID as a [correlation id](../core/logger.md##set_correlation_id-method){target="_blank" rel="nofollow"} automatically. +* **L22**: Since we're in dev, we also use `log_event=True` to automatically log each incoming request for debugging. This can be also set via [environment variables](./index.md#environment-variables){target="_blank" rel="nofollow"}. This is how the logs would look like now: @@ -509,10 +509,10 @@ This is how the logs would look like now: ``` We can now search our logs by the request ID to find a specific operation. Additionally, we can also search our logs for function name, Lambda request ID, Lambda function ARN, find out whether an operation was a cold start, etc. + +From here, we could [set specific keys](../core/logger.md#append_keys-method){target="_blank" rel="nofollow"} to add additional contextual information about a given operation, [log exceptions](../core/logger.md#logging-exceptions){target="_blank" rel="nofollow"} to easily enumerate them later, [sample debug logs](../core/logger.md#sampling-debug-logs){target="_blank" rel="nofollow"}, etc. -From here, we could [set specific keys](../core/logger.md#append_keys-method){target="_blank"} to add additional contextual information about a given operation, [log exceptions](../core/logger.md#logging-exceptions){target="_blank"} to easily enumerate them later, [sample debug logs](../core/logger.md#sampling-debug-logs){target="_blank"}, etc. - -By having structured logs like this, we can easily search and analyse them in [CloudWatch Logs Insight](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html){target="_blank"}. +By having structured logs like this, we can easily search and analyse them in [CloudWatch Logs Insight](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html){target="_blank" rel="nofollow"}. === "CloudWatch Logs Insight Example" ![CloudWatch Logs Insight Example](../media/cloudwatch_logs_insight_example.png) @@ -528,14 +528,14 @@ Combined with structured logs, it is an important step to be able to observe how ### Generating traces -[AWS X-Ray](https://aws.amazon.com/xray/){target="_blank"} is the distributed tracing service we're going to use. But how do we generate application traces in the first place? +[AWS X-Ray](https://aws.amazon.com/xray/){target="_blank" rel="nofollow"} is the distributed tracing service we're going to use. But how do we generate application traces in the first place? -It's a [two-step process](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"}: +It's a [two-step process](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank" rel="nofollow"}: 1. Enable tracing in your Lambda function. 2. Instrument your application code. -Let's explore how we can instrument our code with [AWS X-Ray SDK](https://docs.aws.amazon.com/xray-sdk-for-python/latest/reference/index.html){target="_blank"}, and then simplify it with [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank"} feature. +Let's explore how we can instrument our code with [AWS X-Ray SDK](https://docs.aws.amazon.com/xray-sdk-for-python/latest/reference/index.html){target="_blank" rel="nofollow"}, and then simplify it with [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank" rel="nofollow"} feature. === "app.py" @@ -616,7 +616,7 @@ Let's explore how we can instrument our code with [AWS X-Ray SDK](https://docs.a Let's break it down: -* **L1**: First, we import AWS X-Ray SDK. `xray_recorder` records blocks of code being traced ([subsegment](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-subsegments){target="_blank"}). It also sends generated traces to the AWS X-Ray daemon running in the Lambda service who subsequently forwards them to AWS X-Ray service. +* **L1**: First, we import AWS X-Ray SDK. `xray_recorder` records blocks of code being traced ([subsegment](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-subsegments){target="_blank" rel="nofollow"}). It also sends generated traces to the AWS X-Ray daemon running in the Lambda service who subsequently forwards them to AWS X-Ray service. * **L13,20,27**: We decorate our function so the SDK traces the end-to-end execution, and the argument names the generated block being traced. ???+ question @@ -625,9 +625,9 @@ Let's break it down: We've made the following changes in `template.yaml` for this to work seamless: * **L7-8**: Enables tracing for Amazon API Gateway. -* **L16**: Enables tracing for our Serverless Function. This will also add a managed IAM Policy named [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess){target="_blank"} to allow Lambda to send traces to AWS X-Ray. +* **L16**: Enables tracing for our Serverless Function. This will also add a managed IAM Policy named [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess){target="_blank" rel="nofollow"} to allow Lambda to send traces to AWS X-Ray. -You can now build and deploy our updates with `sam build && sam deploy`. Once deployed, try invoking the application via the API endpoint, and visit [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"} to see how much progress we've made so far!! +You can now build and deploy our updates with `sam build && sam deploy`. Once deployed, try invoking the application via the API endpoint, and visit [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank" rel="nofollow"} to see how much progress we've made so far!! ![AWS X-Ray Console trace view](../media/tracer_xray_sdk_showcase.png) @@ -644,7 +644,7 @@ What we've done helps bring an initial visibility, but we can do so much more. Within AWS X-Ray, we can answer these questions by using two features: tracing **Annotations** and **Metadata**. -**Annotations** are simple key-value pairs that are indexed for use with [filter expressions](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html){target="_blank"}. +**Annotations** are simple key-value pairs that are indexed for use with [filter expressions](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html){target="_blank" rel="nofollow"}. **Metadata** are key-value pairs with values of any type, including objects and lists, but that are not indexed. Let's put them into action. @@ -708,11 +708,11 @@ Let's break it down: * **L44**: We include the final response under `response` key as part of the `handler` subsegment. ???+ info - If you want to understand how the Lambda execution environment (sandbox) works and why cold starts can occur, see this [blog series on Lambda performance](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/){target="_blank"}. + If you want to understand how the Lambda execution environment (sandbox) works and why cold starts can occur, see this [blog series on Lambda performance](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/){target="_blank" rel="nofollow"}. Repeat the process of building, deploying, and invoking your application via the API endpoint. -Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"}, you should now be able to group traces by the `User` and `ColdStart` annotation. +Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank" rel="nofollow"}, you should now be able to group traces by the `User` and `ColdStart` annotation. ![Filtering traces by annotations](../media/tracer_xray_sdk_enriched.png) @@ -724,7 +724,7 @@ If you choose any of the traces available, try opening the `handler` subsegment Cross-cutting concerns like filtering traces by Cold Start, including response as well as exceptions as tracing metadata can take a considerable amount of boilerplate. -We can simplify our previous patterns by using [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank"}; a thin wrapper on top of X-Ray SDK. +We can simplify our previous patterns by using [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank" rel="nofollow"}; a thin wrapper on top of X-Ray SDK. ???+ note You can now safely remove `aws-xray-sdk` from `requirements.txt`; keep `aws-lambda-powertools` only. @@ -773,32 +773,32 @@ Another subtle difference is that you can now run your Lambda functions and unit Powertools for AWS Lambda (Python) optimizes for Lambda compute environment. As such, we add these and other common approaches to accelerate your development, so you don't worry about implementing every cross-cutting concern. ???+ tip - You can [opt-out some of these behaviours](../core/tracer/#advanced){target="_blank"} like disabling response capturing, explicitly patching only X modules, etc. + You can [opt-out some of these behaviours](../core/tracer/#advanced){target="_blank" rel="nofollow"} like disabling response capturing, explicitly patching only X modules, etc. -Repeat the process of building, deploying, and invoking your application via the API endpoint. Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"}, you should see a similar view: +Repeat the process of building, deploying, and invoking your application via the API endpoint. Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank" rel="nofollow"}, you should see a similar view: ![AWS X-Ray Console trace view using Powertools for AWS Lambda (Python) Tracer](../media/tracer_utility_showcase_2.png) ???+ tip - Consider using [Amazon CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank"} as it aggregates AWS X-Ray traces and CloudWatch metrics and logs in one view. + Consider using [Amazon CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank" rel="nofollow"} as it aggregates AWS X-Ray traces and CloudWatch metrics and logs in one view. From here, you can browse to specific logs in CloudWatch Logs Insight, Metrics Dashboard or AWS X-Ray traces. ![CloudWatch ServiceLens View](../media/tracer_utility_showcase_3.png) ???+ info - For more information on Amazon CloudWatch ServiceLens, please visit [link](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceLens.html){target="_blank"}. + For more information on Amazon CloudWatch ServiceLens, please visit [link](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceLens.html){target="_blank" rel="nofollow"}. ## Custom Metrics ### Creating metrics Let's add custom metrics to better understand our application and business behavior (e.g. number of reservations, etc.). - -By default, AWS Lambda adds [invocation and performance metrics](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-types){target="_blank"}, and Amazon API Gateway adds [latency and some HTTP metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metrics){target="_blank"}. + +By default, AWS Lambda adds [invocation and performance metrics](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-types){target="_blank" rel="nofollow"}, and Amazon API Gateway adds [latency and some HTTP metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metrics){target="_blank" rel="nofollow"}. ???+ tip - You can [optionally enable detailed metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metricdimensions){target="_blank"} per each API route, stage, and method in API Gateway. + You can [optionally enable detailed metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metricdimensions){target="_blank" rel="nofollow"} per each API route, stage, and method in API Gateway. Let's expand our application with custom metrics using AWS SDK to see how it works, then let's upgrade it with Powertools for AWS Lambda (Python) :-) @@ -917,16 +917,16 @@ Let's expand our application with custom metrics using AWS SDK to see how it wor There's a lot going on, let's break this down: -* **L10**: We define a container where all of our application metrics will live `MyApp`, a.k.a [Metrics Namespace](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html){target="_blank"}. +* **L10**: We define a container where all of our application metrics will live `MyApp`, a.k.a [Metrics Namespace](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html){target="_blank" rel="nofollow"}. * **L14**: We initialize a CloudWatch client to send metrics later. -* **L19-47**: We create a custom function to prepare and send `ColdStart` and `SuccessfulGreetings` metrics using CloudWatch expected data structure. We also set [dimensions](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Dimension){target="_blank"} of these metrics. +* **L19-47**: We create a custom function to prepare and send `ColdStart` and `SuccessfulGreetings` metrics using CloudWatch expected data structure. We also set [dimensions](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Dimension){target="_blank" rel="nofollow"} of these metrics. * Think of them as metadata to define to slice and dice them later; an unique metric is a combination of metric name + metric dimension(s). * **L55,64**: We call our custom function to create metrics for every greeting received. ???+ question But what permissions do I need to send metrics to CloudWatch? -Within `template.yaml`, we add [CloudWatchPutMetricPolicy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-template-list.html#cloudwatch-put-metric-policy){target="_blank"} policy in SAM. +Within `template.yaml`, we add [CloudWatchPutMetricPolicy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-template-list.html#cloudwatch-put-metric-policy){target="_blank" rel="nofollow"} policy in SAM. ???+ note "Adding metrics via AWS SDK gives a lot of flexibility at a cost" `put_metric_data` is a synchronous call to CloudWatch Metrics API. This means establishing a connection to CloudWatch endpoint, sending metrics payload, and waiting from a response. @@ -935,12 +935,12 @@ Within `template.yaml`, we add [CloudWatchPutMetricPolicy](https://docs.aws.amaz ### Simplifying with Metrics -[Powertools for AWS Lambda (Python) Metrics](../core/metrics.md){target="_blank} uses [Amazon CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html){target="_blank"} to create custom metrics **asynchronously** via a native integration with Lambda. +[Powertools for AWS Lambda (Python) Metrics](../core/metrics.md){target="_blank} uses [Amazon CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html){target="_blank" rel="nofollow"} to create custom metrics **asynchronously** via a native integration with Lambda. In general terms, EMF is a specification that expects metrics in a JSON payload within CloudWatch Logs. Lambda ingests all logs emitted by a given function into CloudWatch Logs. CloudWatch automatically looks up for log entries that follow the EMF format and transforms them into a CloudWatch metric. ???+ info - If you are interested in the details of the EMF mechanism, follow [blog post](https://aws.amazon.com/blogs/mt/enhancing-workload-observability-using-amazon-cloudwatch-embedded-metric-format/){target="_blank"}. + If you are interested in the details of the EMF mechanism, follow [blog post](https://aws.amazon.com/blogs/mt/enhancing-workload-observability-using-amazon-cloudwatch-embedded-metric-format/){target="_blank" rel="nofollow"}. Let's implement that using [Metrics](../core/metrics.md){target="_blank}: @@ -991,15 +991,15 @@ That's a lot less boilerplate code! Let's break this down: * **L9**: We initialize `Metrics` with our service name (`APP`) and metrics namespace (`MyApp`), reducing the need to add the `service` dimension for every metric and setting the namespace later * **L18, 27**: We use `add_metric` similarly to our custom function, except we now have an enum `MetricCount` to help us understand which Metric Units we have at our disposal * **L33**: We use `@metrics.log_metrics` decorator to ensure that our metrics are aligned with the EMF output and validated before-hand, like in case we forget to set namespace, or accidentally use a metric unit as a string that doesn't exist in CloudWatch. -* **L33**: We also use `capture_cold_start_metric=True` so we don't have to handle that logic either. Note that [Metrics](../core/metrics.md){target="_blank"} does not publish a warm invocation metric (ColdStart=0) for cost reasons. As such, treat the absence (sparse metric) as a non-cold start invocation. +* **L33**: We also use `capture_cold_start_metric=True` so we don't have to handle that logic either. Note that [Metrics](../core/metrics.md){target="_blank" rel="nofollow"} does not publish a warm invocation metric (ColdStart=0) for cost reasons. As such, treat the absence (sparse metric) as a non-cold start invocation. -Repeat the process of building, deploying, and invoking your application via the API endpoint a few times to generate metrics - [Artillery](https://www.artillery.io/){target="_blank"} and [K6.io](https://k6.io/open-source){target="_blank"} are quick ways to generate some load. +Repeat the process of building, deploying, and invoking your application via the API endpoint a few times to generate metrics - [Artillery](https://www.artillery.io/){target="_blank" rel="nofollow"} and [K6.io](https://k6.io/open-source){target="_blank" rel="nofollow"} are quick ways to generate some load. Within [CloudWatch Metrics view](https://console.aws.amazon.com/cloudwatch/home#metricsV2:graph=~()){target="_blank}, you should see `MyApp` custom namespace with your custom metrics there and `SuccessfulGreetings` available to graph. ![Custom Metrics Example](../media/metrics_utility_showcase.png) -If you're curious about how the EMF portion of your function logs look like, you can quickly go to [CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank"}, choose your function and open logs. You will see a similar entry that looks like this: +If you're curious about how the EMF portion of your function logs look like, you can quickly go to [CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank" rel="nofollow"}, choose your function and open logs. You will see a similar entry that looks like this: ```json { @@ -1034,15 +1034,15 @@ If you're curious about how the EMF portion of your function logs look like, you ## Final considerations We covered a lot of ground here and we only scratched the surface of the feature set available within Powertools for AWS Lambda (Python). - -When it comes to the observability features ([Tracer](../core/tracer.md){target="_blank"}, [Metrics](../core/metrics.md){target="_blank"}, [Logging](../core/logger.md){target="_blank"}), don't stop there! The goal here is to ensure you can ask arbitrary questions to assess your system's health; these features are only part of the wider story! + +When it comes to the observability features ([Tracer](../core/tracer.md){target="_blank" rel="nofollow"}, [Metrics](../core/metrics.md){target="_blank" rel="nofollow"}, [Logging](../core/logger.md){target="_blank" rel="nofollow"}), don't stop there! The goal here is to ensure you can ask arbitrary questions to assess your system's health; these features are only part of the wider story! This requires a change in mindset to ensure operational excellence is part of the software development lifecycle. ???+ tip - You can find more details on other leading practices described in the [Well-Architected Serverless Lens](https://aws.amazon.com/blogs/aws/new-serverless-lens-in-aws-well-architected-tool/){target="_blank"}. + You can find more details on other leading practices described in the [Well-Architected Serverless Lens](https://aws.amazon.com/blogs/aws/new-serverless-lens-in-aws-well-architected-tool/){target="_blank" rel="nofollow"}. Powertools for AWS Lambda (Python) is largely designed to make some of these practices easier to adopt from day 1. ???+ question "Have ideas for other tutorials?" - You can open up a [documentation issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=documentation&template=documentation-improvements.md&title=Tutorial%20Suggestion){target="_blank"}, or via e-mail [aws-lambda-powertools-feedback@amazon.com](mailto:aws-lambda-powertools-feedback@amazon.com). + You can open up a [documentation issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=documentation&template=documentation-improvements.md&title=Tutorial%20Suggestion){target="_blank" rel="nofollow"}, or via e-mail [aws-lambda-powertools-feedback@amazon.com](mailto:aws-lambda-powertools-feedback@amazon.com). diff --git a/docs/upgrade.md b/docs/upgrade.md index 064c6a9657a..509bffda15c 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -9,7 +9,7 @@ description: Guide to update between major Powertools for AWS Lambda (Python) ve !!! warning "On March 31st, 2023, Powertools for AWS Lambda (Python) v1 reached 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 (Python), we will keep [Pypi](https://pypi.org/project/aws-lambda-powertools/){target="_blank"} v1 releases and documentation 1.x versions to prevent any disruption. +Given our commitment to all of our customers using Powertools for AWS Lambda (Python), we will keep [Pypi](https://pypi.org/project/aws-lambda-powertools/){target="_blank" rel="nofollow"} v1 releases and documentation 1.x versions to prevent any disruption. ## Migrate to v2 from v1 @@ -20,20 +20,20 @@ We've made minimal breaking changes to make your transition to v2 as smooth as p | Area | Change | Code change required | IAM Permissions change required | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------------- | | **Batch** | Removed legacy [SQS batch processor](#legacy-sqs-batch-processor) in favour of **`BatchProcessor`**. | Yes | - | -| **Environment variables** | Removed legacy **`POWERTOOLS_EVENT_HANDLER_DEBUG`** in favour of [`POWERTOOLS_DEV`](index.md#optimizing-for-non-production-environments){target="_blank"}. | - | - | -| **Event Handler** | Updated [headers response format](#event-handler-headers-response-format) due to [multi-value headers and cookie support](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank"}. | Tests only | - | +| **Environment variables** | Removed legacy **`POWERTOOLS_EVENT_HANDLER_DEBUG`** in favour of [`POWERTOOLS_DEV`](index.md#optimizing-for-non-production-environments){target="_blank" rel="nofollow"}. | - | - | +| **Event Handler** | Updated [headers response format](#event-handler-headers-response-format) due to [multi-value headers and cookie support](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank" rel="nofollow"}. | Tests only | - | | **Event Source Data Classes** | Replaced [DynamoDBStreamEvent](#dynamodbstreamevent-in-event-source-data-classes) `AttributeValue` with native Python types. | Yes | - | | **Feature Flags** / **Parameters** | Updated [AppConfig API calls](#feature-flags-and-appconfig-parameter-utility) due to **`GetConfiguration`** API deprecation. | - | Yes | | **Idempotency** | Updated [partition key](#idempotency-partition-key-format) to include fully qualified function/method names. | - | - | ### First Steps -!!! note "All dependencies are optional now. [Tracer](core/tracer.md#install){target="_blank"}, [Validation](./utilities/validation.md#install){target="_blank"}, and [Parser](./utilities/parser.md){target="_blank"} now require additional dependencies." +!!! note "All dependencies are optional now. [Tracer](core/tracer.md#install){target="_blank" rel="nofollow"}, [Validation](./utilities/validation.md#install){target="_blank" rel="nofollow"}, and [Parser](./utilities/parser.md){target="_blank" rel="nofollow"} now require additional dependencies." Before you start, we suggest making a copy of your current working project or create a new branch with git. 1. **Upgrade** Python to at least v3.7 -2. **Ensure** you have the latest version via [Lambda Layer or PyPi](index.md#install){target="_blank"}. +2. **Ensure** you have the latest version via [Lambda Layer or PyPi](index.md#install){target="_blank" rel="nofollow"}. 3. **Review** the following sections to confirm whether they affect your code ## Legacy SQS Batch Processor @@ -44,7 +44,7 @@ You can migrate to `BatchProcessor` with the following changes: 1. If you use **`sqs_batch_decorator`**, change to **`batch_processor`** decorator 2. If you use **`PartialSQSProcessor`**, change to **`BatchProcessor`** -3. [Enable **`ReportBatchItemFailures`** in your Lambda Event Source](../utilities/batch#required-resources){target="_blank"} +3. [Enable **`ReportBatchItemFailures`** in your Lambda Event Source](../utilities/batch#required-resources){target="_blank" rel="nofollow"} 4. Change your Lambda Handler to return the new response format === "[Before] Decorator" @@ -139,7 +139,7 @@ Previously, custom headers were available under `headers` key in the Event Handl } ``` -In V2, we add all headers under `multiValueHeaders` key. This enables seamless support for multi-value headers and cookies in [fine grained responses](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank"}. +In V2, we add all headers under `multiValueHeaders` key. This enables seamless support for multi-value headers and cookies in [fine grained responses](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank" rel="nofollow"}. ```python title="V2 response headers" hl_lines="2" { @@ -151,7 +151,7 @@ In V2, we add all headers under `multiValueHeaders` key. This enables seamless s ## DynamoDBStreamEvent in Event Source Data Classes -!!! info "This also applies if you're using [**DynamoDB BatchProcessor**](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-dynamodb){target="_blank"}." +!!! info "This also applies if you're using [**DynamoDB BatchProcessor**](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-dynamodb){target="_blank" rel="nofollow"}." You will now receive native Python types when accessing DynamoDB records via `keys`, `new_image`, and `old_image` attributes in `DynamoDBStreamEvent`. @@ -196,7 +196,7 @@ def lambda_handler(event: DynamoDBStreamEvent, context): !!! note "No code changes required" -We replaced `GetConfiguration` API ([now deprecated](https://github.com/aws-powertools/powertools-lambda-python/issues/1506#issuecomment-1266645884){target="_blank"}) with `GetLatestConfiguration` and `StartConfigurationSession`. +We replaced `GetConfiguration` API ([now deprecated](https://github.com/aws-powertools/powertools-lambda-python/issues/1506#issuecomment-1266645884){target="_blank" rel="nofollow"}) with `GetLatestConfiguration` and `StartConfigurationSession`. As such, you must update your IAM Role permissions to allow the following IAM actions: @@ -217,7 +217,7 @@ Previously, we used the function/method name to generate the partition key value In V2, we now distinguish between distinct classes or modules that may have the same function/method name. -[For example](https://github.com/aws-powertools/powertools-lambda-python/issues/1330){target="_blank"}, an ABC or Protocol class may have multiple implementations of `process_payment` method and may have different results. +[For example](https://github.com/aws-powertools/powertools-lambda-python/issues/1330){target="_blank" rel="nofollow"}, an ABC or Protocol class may have multiple implementations of `process_payment` method and may have different results. diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 1b9894a0256..488be06e60b 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -21,14 +21,14 @@ If your function fails to process any message from the batch, the entire batch r With this utility, batch records are processed individually – only messages that failed to be processed return to the queue or stream for a further retry. This works when two mechanisms are in place: 1. `ReportBatchItemFailures` is set in your SQS, Kinesis, or DynamoDB event source properties -2. [A specific response](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank"} is returned so Lambda knows which records should not be deleted during partial responses +2. [A specific response](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank" rel="nofollow"} is returned so Lambda knows which records should not be deleted during partial responses ???+ warning "Warning: This utility lowers the chance of processing records more than once; it does not guarantee it" - We recommend implementing processing logic in an [idempotent manner](idempotency.md){target="_blank"} wherever possible. + We recommend implementing processing logic in an [idempotent manner](idempotency.md){target="_blank" rel="nofollow"} wherever possible. - You can find more details on how Lambda works with either [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html){target="_blank"}, [Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html){target="_blank"}, or [DynamoDB](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html){target="_blank"} in the AWS Documentation. + You can find more details on how Lambda works with either [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html){target="_blank" rel="nofollow"}, [Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html){target="_blank" rel="nofollow"}, or [DynamoDB](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html){target="_blank" rel="nofollow"} in the AWS Documentation. ## Getting started @@ -63,7 +63,7 @@ The remaining sections of the documentation will rely on these samples. For comp Processing batches from SQS works in three stages: 1. Instantiate **`BatchProcessor`** and choose **`EventType.SQS`** for the event type -2. Define your function to handle each batch record, and use [`SQSRecord`](data_classes.md#sqs){target="_blank"} type annotation for autocompletion +2. Define your function to handle each batch record, and use [`SQSRecord`](data_classes.md#sqs){target="_blank" rel="nofollow"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing ???+ info @@ -103,7 +103,7 @@ Processing batches from SQS works in three stages: #### FIFO queues -When using [SQS FIFO queues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html){target="_blank"}, we will stop processing messages after the first failure, and return all failed and unprocessed messages in `batchItemFailures`. +When using [SQS FIFO queues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html){target="_blank" rel="nofollow"}, we will stop processing messages after the first failure, and return all failed and unprocessed messages in `batchItemFailures`. This helps preserve the ordering of messages in your queue. === "Recommended" @@ -129,7 +129,7 @@ This helps preserve the ordering of messages in your queue. Processing batches from Kinesis works in three stages: 1. Instantiate **`BatchProcessor`** and choose **`EventType.KinesisDataStreams`** for the event type -2. Define your function to handle each batch record, and use [`KinesisStreamRecord`](data_classes.md#kinesis-streams){target="_blank"} type annotation for autocompletion +2. Define your function to handle each batch record, and use [`KinesisStreamRecord`](data_classes.md#kinesis-streams){target="_blank" rel="nofollow"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing ???+ info @@ -172,7 +172,7 @@ Processing batches from Kinesis works in three stages: Processing batches from DynamoDB Streams works in three stages: 1. Instantiate **`BatchProcessor`** and choose **`EventType.DynamoDBStreams`** for the event type -2. Define your function to handle each batch record, and use [`DynamoDBRecord`](data_classes.md#dynamodb-streams){target="_blank"} type annotation for autocompletion +2. Define your function to handle each batch record, and use [`DynamoDBRecord`](data_classes.md#dynamodb-streams){target="_blank" rel="nofollow"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing ???+ info @@ -220,7 +220,7 @@ All records in the batch will be passed to this handler for processing, even if ### Processing messages asynchronously -!!! tip "New to AsyncIO? Read this [comprehensive guide first](https://realpython.com/async-io-python/){target="_blank"}." +!!! tip "New to AsyncIO? Read this [comprehensive guide first](https://realpython.com/async-io-python/){target="_blank" rel="nofollow"}." You can use `AsyncBatchProcessor` class and `async_process_partial_response` function to process messages concurrently. @@ -238,7 +238,7 @@ You can use `AsyncBatchProcessor` class and `async_process_partial_response` fun ???+ warning "Using tracer?" `AsyncBatchProcessor` uses `asyncio.gather` which can cause side effects and reach trace limits at high concurrency. - See [Tracing concurrent asynchronous functions](../core/tracer.md#concurrent-asynchronous-functions){target="_blank"}. + See [Tracing concurrent asynchronous functions](../core/tracer.md#concurrent-asynchronous-functions){target="_blank" rel="nofollow"}. ## Advanced @@ -299,7 +299,7 @@ Use the context manager to access a list of all returned values from your `recor Within your `record_handler` function, you might need access to the Lambda context to determine how much time you have left before your function times out. -We can automatically inject the [Lambda context](https://docs.aws.amazon.com/lambda/latest/dg/python-context.html){target="_blank"} into your `record_handler` if your function signature has a parameter named `lambda_context`. When using a context manager, you also need to pass the Lambda context object like in the example below. +We can automatically inject the [Lambda context](https://docs.aws.amazon.com/lambda/latest/dg/python-context.html){target="_blank" rel="nofollow"} into your `record_handler` if your function signature has a parameter named `lambda_context`. When using a context manager, you also need to pass the Lambda context object like in the example below. === "Recommended" @@ -356,7 +356,7 @@ You can then use this class as a context manager, or pass it to `batch_processor When using Tracer to capture responses for each batch record processing, you might exceed 64K of tracing data depending on what you return from your `record_handler` function, or how big is your batch size. -If that's the case, you can configure [Tracer to disable response auto-capturing](../core/tracer.md#disabling-response-auto-capture){target="_blank"}. +If that's the case, you can configure [Tracer to disable response auto-capturing](../core/tracer.md#disabling-response-auto-capture){target="_blank" rel="nofollow"}. ```python hl_lines="17" title="Disabling Tracer response auto-capturing" --8<-- "examples/batch_processing/src/disable_tracing.py" @@ -404,7 +404,7 @@ As 2.12.0, `process_partial_response` and `async_process_partial_response` are t When using Sentry.io for error monitoring, you can override `failure_handler` to capture each processing exception with Sentry SDK: -> Credits to [Charles-Axel Dein](https://github.com/aws-powertools/powertools-lambda-python/issues/293#issuecomment-781961732){target="_blank"} +> Credits to [Charles-Axel Dein](https://github.com/aws-powertools/powertools-lambda-python/issues/293#issuecomment-781961732){target="_blank" rel="nofollow"} ```python hl_lines="1 7-8" title="Integrating error tracking with Sentry.io" --8<-- "examples/batch_processing/src/sentry_error_tracking.py" diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 7b3aa74e275..ca41dbe01ea 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -111,8 +111,8 @@ Log Data Event for Troubleshooting ### Active MQ -It is used for [Active MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank"}, also see -the [AWS blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-as-an-event-source-for-aws-lambda/){target="_blank"} +It is used for [Active MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank" rel="nofollow"}, also see +the [AWS blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-as-an-event-source-for-aws-lambda/){target="_blank" rel="nofollow"} for more details. === "app.py" @@ -138,7 +138,7 @@ for more details. > New in 1.20.0 -It is used for [API Gateway Rest API Lambda Authorizer payload](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html){target="_blank"}. +It is used for [API Gateway Rest API Lambda Authorizer payload](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html){target="_blank" rel="nofollow"}. Use **`APIGatewayAuthorizerRequestEvent`** for type `REQUEST` and **`APIGatewayAuthorizerTokenEvent`** for type `TOKEN`. @@ -234,8 +234,8 @@ Use **`APIGatewayAuthorizerRequestEvent`** for type `REQUEST` and **`APIGatewayA > New in 1.20.0 -It is used for [API Gateway HTTP API Lambda Authorizer payload version 2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html){target="_blank"}. -See also [this blog post](https://aws.amazon.com/blogs/compute/introducing-iam-and-lambda-authorizers-for-amazon-api-gateway-http-apis/){target="_blank"} for more details. +It is used for [API Gateway HTTP API Lambda Authorizer payload version 2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html){target="_blank" rel="nofollow"}. +See also [this blog post](https://aws.amazon.com/blogs/compute/introducing-iam-and-lambda-authorizers-for-amazon-api-gateway-http-apis/){target="_blank" rel="nofollow"} for more details. === "app.py" @@ -320,9 +320,9 @@ Is it used for Application load balancer event. > New in 1.20.0 -Used when building an [AWS_LAMBDA Authorization](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-lambda-authorization){target="_blank"} with AppSync. -See blog post [Introducing Lambda authorization for AWS AppSync GraphQL APIs](https://aws.amazon.com/blogs/mobile/appsync-lambda-auth/){target="_blank"} -or read the Amplify documentation on using [AWS Lambda for authorization](https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js#aws-lambda){target="_blank"} with AppSync. +Used when building an [AWS_LAMBDA Authorization](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-lambda-authorization){target="_blank" rel="nofollow"} with AppSync. +See blog post [Introducing Lambda authorization for AWS AppSync GraphQL APIs](https://aws.amazon.com/blogs/mobile/appsync-lambda-auth/){target="_blank" rel="nofollow"} +or read the Amplify documentation on using [AWS Lambda for authorization](https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js#aws-lambda){target="_blank" rel="nofollow"} with AppSync. In this example extract the `requestId` as the `correlation_id` for logging, used `@event_source` decorator and builds the AppSync authorizer using the `AppSyncAuthorizerResponse` helper. @@ -368,8 +368,8 @@ In this example extract the `requestId` as the `correlation_id` for logging, use > New in 1.12.0 -Used when building Lambda GraphQL Resolvers with [Amplify GraphQL Transform Library](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank"} (`@function`), -and [AppSync Direct Lambda Resolvers](https://aws.amazon.com/blogs/mobile/appsync-direct-lambda/){target="_blank"}. +Used when building Lambda GraphQL Resolvers with [Amplify GraphQL Transform Library](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank" rel="nofollow"} (`@function`), +and [AppSync Direct Lambda Resolvers](https://aws.amazon.com/blogs/mobile/appsync-direct-lambda/){target="_blank" rel="nofollow"}. In this example, we also use the new Logger `correlation_id` and built-in `correlation_paths` to extract, if available, X-Ray Trace ID in AppSync request headers: @@ -538,7 +538,7 @@ decompress and parse json data from the event. #### Kinesis integration -[When streaming CloudWatch Logs to a Kinesis Data Stream](https://aws.amazon.com/premiumsupport/knowledge-center/streaming-cloudwatch-logs/){target="_blank"} (cross-account or not), you can use `extract_cloudwatch_logs_from_event` to decode, decompress and extract logs as `CloudWatchLogsDecodedData` to ease log processing. +[When streaming CloudWatch Logs to a Kinesis Data Stream](https://aws.amazon.com/premiumsupport/knowledge-center/streaming-cloudwatch-logs/){target="_blank" rel="nofollow"} (cross-account or not), you can use `extract_cloudwatch_logs_from_event` to decode, decompress and extract logs as `CloudWatchLogsDecodedData` to ease log processing. === "app.py" @@ -560,7 +560,7 @@ decompress and parse json data from the event. return "nothing to be processed" ``` -Alternatively, you can use `extract_cloudwatch_logs_from_record` to seamless integrate with the [Batch utility](./batch.md){target="_blank"} for more robust log processing. +Alternatively, you can use `extract_cloudwatch_logs_from_record` to seamless integrate with the [Batch utility](./batch.md){target="_blank" rel="nofollow"} for more robust log processing. === "app.py" @@ -636,7 +636,7 @@ Data classes and utility functions to help create continuous delivery pipelines ### Cognito User Pool -Cognito User Pools have several [different Lambda trigger sources](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-identity-pools-working-with-aws-lambda-trigger-sources){target="_blank"}, all of which map to a different data class, which +Cognito User Pools have several [different Lambda trigger sources](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-identity-pools-working-with-aws-lambda-trigger-sources){target="_blank" rel="nofollow"}, all of which map to a different data class, which can be imported from `aws_lambda_powertools.data_classes.cognito_user_pool_event`: | Trigger/Event Source | Data Class | @@ -671,7 +671,7 @@ can be imported from `aws_lambda_powertools.data_classes.cognito_user_pool_event ???+ note In this example we are modifying the wrapped dict response fields, so we need to return the json serializable wrapped event in `event.raw_event`. -This example is based on the AWS Cognito docs for [Define Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-define-auth-challenge.html){target="_blank"}. +This example is based on the AWS Cognito docs for [Define Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-define-auth-challenge.html){target="_blank" rel="nofollow"}. === "app.py" @@ -825,7 +825,7 @@ This example is based on the AWS Cognito docs for [Define Auth Challenge Lambda #### Create Auth Challenge Example -This example is based on the AWS Cognito docs for [Create Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-create-auth-challenge.html){target="_blank"}. +This example is based on the AWS Cognito docs for [Create Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-create-auth-challenge.html){target="_blank" rel="nofollow"}. === "app.py" @@ -844,7 +844,7 @@ This example is based on the AWS Cognito docs for [Create Auth Challenge Lambda #### Verify Auth Challenge Response Example -This example is based on the AWS Cognito docs for [Verify Auth Challenge Response Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-verify-auth-challenge-response.html){target="_blank"}. +This example is based on the AWS Cognito docs for [Verify Auth Challenge Response Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-verify-auth-challenge-response.html){target="_blank" rel="nofollow"}. === "app.py" @@ -936,7 +936,7 @@ The class automatically deserializes DynamoDB types into their equivalent Python ### Kafka -This example is based on the AWS docs for [Amazon MSK](https://docs.aws.amazon.com/lambda/latest/dg/with-msk.html){target="_blank"} and [self-managed Apache Kafka](https://docs.aws.amazon.com/lambda/latest/dg/with-kafka.html){target="_blank"}. +This example is based on the AWS docs for [Amazon MSK](https://docs.aws.amazon.com/lambda/latest/dg/with-msk.html){target="_blank" rel="nofollow"} and [self-managed Apache Kafka](https://docs.aws.amazon.com/lambda/latest/dg/with-kafka.html){target="_blank" rel="nofollow"}. === "app.py" @@ -1001,8 +1001,8 @@ function to access the data either as json or plain text, depending on the origi ### Rabbit MQ -It is used for [Rabbit MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank"}, also see -the [blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-for-rabbitmq-as-an-event-source-for-lambda/){target="_blank"} +It is used for [Rabbit MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank" rel="nofollow"}, also see +the [blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-for-rabbitmq-as-an-event-source-for-lambda/){target="_blank" rel="nofollow"} for more details. === "app.py" @@ -1047,7 +1047,7 @@ for more details. ### S3 Object Lambda -This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda – Use Your Code to Process Data as It Is Being Retrieved from S3](https://aws.amazon.com/blogs/aws/introducing-amazon-s3-object-lambda-use-your-code-to-process-data-as-it-is-being-retrieved-from-s3/){target="_blank"}. +This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda – Use Your Code to Process Data as It Is Being Retrieved from S3](https://aws.amazon.com/blogs/aws/introducing-amazon-s3-object-lambda-use-your-code-to-process-data-as-it-is-being-retrieved-from-s3/){target="_blank" rel="nofollow"}. === "app.py" @@ -1147,7 +1147,7 @@ This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda You can register your Lambda functions as targets within an Amazon VPC Lattice service network. By doing this, your Lambda function becomes a service within the network, and clients that have access to the VPC Lattice service network can call your service. -[Click here](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"} for more information about using AWS Lambda with Amazon VPC Lattice. +[Click here](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank" rel="nofollow"} for more information about using AWS Lambda with Amazon VPC Lattice. === "app.py" diff --git a/docs/utilities/feature_flags.md b/docs/utilities/feature_flags.md index 890f4f0f8c2..1b00cb46835 100644 --- a/docs/utilities/feature_flags.md +++ b/docs/utilities/feature_flags.md @@ -6,7 +6,7 @@ description: Utility The feature flags utility provides a simple rule engine to define when one or multiple features should be enabled depending on the input. ???+ info - When using `AppConfigStore`, we currently only support AppConfig using [freeform configuration profile](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html#appconfig-creating-configuration-and-profile-free-form-configurations){target="_blank"} . + When using `AppConfigStore`, we currently only support AppConfig using [freeform configuration profile](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html#appconfig-creating-configuration-and-profile-free-form-configurations){target="_blank" rel="nofollow"} . ## Key features @@ -25,19 +25,19 @@ Feature flags are used to modify behaviour without changing the application's co **Dynamic flags**. Indicates something can have varying states, for example enable a list of premium features for customer X not Y. ???+ tip - You can use [Parameters utility](parameters.md){target="_blank"} for static flags while this utility can do both static and dynamic feature flags. + You can use [Parameters utility](parameters.md){target="_blank" rel="nofollow"} for static flags while this utility can do both static and dynamic feature flags. ???+ warning Be mindful that feature flags can increase the complexity of your application over time; use them sparingly. If you want to learn more about feature flags, their variations and trade-offs, check these articles: -* [Feature Toggles (aka Feature Flags) - Pete Hodgson](https://martinfowler.com/articles/feature-toggles.html){target="_blank"} -* [AWS Lambda Feature Toggles Made Simple - Ran Isenberg](https://isenberg-ran.medium.com/aws-lambda-feature-toggles-made-simple-580b0c444233){target="_blank"} -* [Feature Flags Getting Started - CloudBees](https://www.cloudbees.com/blog/ultimate-feature-flag-guide){target="_blank"} +* [Feature Toggles (aka Feature Flags) - Pete Hodgson](https://martinfowler.com/articles/feature-toggles.html){target="_blank" rel="nofollow"} +* [AWS Lambda Feature Toggles Made Simple - Ran Isenberg](https://isenberg-ran.medium.com/aws-lambda-feature-toggles-made-simple-580b0c444233){target="_blank" rel="nofollow"} +* [Feature Flags Getting Started - CloudBees](https://www.cloudbees.com/blog/ultimate-feature-flag-guide){target="_blank" rel="nofollow"} ???+ note - AWS AppConfig requires two API calls to fetch configuration for the first time. You can improve latency by consolidating your feature settings in a single [Configuration](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html){target="_blank"}. + AWS AppConfig requires two API calls to fetch configuration for the first time. You can improve latency by consolidating your feature settings in a single [Configuration](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html){target="_blank" rel="nofollow"}. ## Getting started @@ -47,7 +47,7 @@ When using the default store `AppConfigStore`, your Lambda function IAM Role mus ### Required resources -By default, this utility provides [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank"} as a configuration store. +By default, this utility provides [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank" rel="nofollow"} as a configuration store. The following sample infrastructure will be used throughout this documentation: @@ -255,8 +255,8 @@ You can also have features enabled only at specific days, for example: enable ch ``` ???+ info "How should I use timezones?" - You can use any [IANA time zone](https://www.iana.org/time-zones){target="_blank"} (as originally specified - in [PEP 615](https://peps.python.org/pep-0615/){target="_blank"}) as part of your rules definition. + You can use any [IANA time zone](https://www.iana.org/time-zones){target="_blank" rel="nofollow"} (as originally specified + in [PEP 615](https://peps.python.org/pep-0615/){target="_blank" rel="nofollow"}) as part of your rules definition. Powertools for AWS Lambda (Python) takes care of converting and calculate the correct timestamps for you. When using `SCHEDULE_BETWEEN_DATETIME_RANGE`, use timestamps without timezone information, and @@ -448,7 +448,7 @@ The `action` configuration can have the following values, where the expressions | Key | Meaning | | ------------------- | ----------------------------------------------------------------------------------------- | | CURRENT_TIME | The current time, 24 hour format (HH:mm) | - | CURRENT_DATETIME | The current datetime ([ISO8601](https://en.wikipedia.org/wiki/ISO_8601){target="_blank"}) | + | CURRENT_DATETIME | The current datetime ([ISO8601](https://en.wikipedia.org/wiki/ISO_8601){target="_blank" rel="nofollow"}) | | CURRENT_DAY_OF_WEEK | The current day of the week (Monday-Sunday) | If not specified, the timezone used for calculations will be UTC. @@ -500,8 +500,8 @@ These are the available options for further customization. | **name** | `""` | AWS AppConfig Configuration name, e.g `features` | | **envelope** | `None` | JMESPath expression to use to extract feature flags configuration from AWS AppConfig configuration | | **max_age** | `5` | Number of seconds to cache feature flags configuration fetched from AWS AppConfig | -| **sdk_config** | `None` | [Botocore Config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank"} | -| **jmespath_options** | `None` | For advanced use cases when you want to bring your own [JMESPath functions](https://github.com/jmespath/jmespath.py#custom-functions){target="_blank"} | +| **sdk_config** | `None` | [Botocore Config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank" rel="nofollow"} | +| **jmespath_options** | `None` | For advanced use cases when you want to bring your own [JMESPath functions](https://github.com/jmespath/jmespath.py#custom-functions){target="_blank" rel="nofollow"} | | **logger** | `logging.Logger` | Logger to use for debug. You can optionally supply an instance of Powertools for AWS Lambda (Python) Logger. | === "appconfig_provider_options.py" @@ -577,6 +577,6 @@ You can unit test your feature flags locally and independently without setting u | Method | When to use | Requires new deployment on changes | Supported services | | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ----------------------------------------------------- | -| **[Environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html){target="_blank"}** | Simple configuration that will rarely if ever change, because changing it requires a Lambda function deployment. | Yes | Lambda | -| **[Parameters utility](parameters.md){target="_blank"}** | Access to secrets, or fetch parameters in different formats from AWS System Manager Parameter Store or Amazon DynamoDB. | No | Parameter Store, DynamoDB, Secrets Manager, AppConfig | +| **[Environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html){target="_blank" rel="nofollow"}** | Simple configuration that will rarely if ever change, because changing it requires a Lambda function deployment. | Yes | Lambda | +| **[Parameters utility](parameters.md){target="_blank" rel="nofollow"}** | Access to secrets, or fetch parameters in different formats from AWS System Manager Parameter Store or Amazon DynamoDB. | No | Parameter Store, DynamoDB, Secrets Manager, AppConfig | | **Feature flags utility** | Rule engine to define when one or multiple features should be enabled depending on the input. | No | AppConfig | diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index bfd65d0a1f6..0d018efaed1 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -74,7 +74,7 @@ If you're not [changing the default configuration for the DynamoDB persistence l | TTL attribute name | `expiration` | This can only be configured after your table is created if you're using AWS Console | ???+ tip "Tip: You can share a single state table for all functions" - You can reuse the same DynamoDB table to store idempotency state. We add `module_name` and [qualified name for classes and functions](https://peps.python.org/pep-3155/){target="_blank"} in addition to the idempotency key as a hash key. + You can reuse the same DynamoDB table to store idempotency state. We add `module_name` and [qualified name for classes and functions](https://peps.python.org/pep-3155/){target="_blank" rel="nofollow"} in addition to the idempotency key as a hash key. === "AWS Serverless Application Model (SAM) example" @@ -94,14 +94,14 @@ If you're not [changing the default configuration for the DynamoDB persistence l ``` ???+ 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){target="_blank"}. + 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){target="_blank" rel="nofollow"}. 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/){target="_blank"} to + see 1WCU and 1RCU. Review the [DynamoDB pricing documentation](https://aws.amazon.com/dynamodb/pricing/){target="_blank" rel="nofollow"} to estimate the cost. ### Idempotent decorator @@ -135,7 +135,7 @@ Similar to [idempotent decorator](#idempotent-decorator), you can use `idempoten When using `idempotent_function`, you must tell us which keyword parameter in your function signature has the data we should use via **`data_keyword_argument`**. -!!! tip "We support JSON serializable data, [Python Dataclasses](https://docs.python.org/3.7/library/dataclasses.html){target="_blank"}, [Parser/Pydantic Models](parser.md){target="_blank"}, and our [Event Source Data Classes](./data_classes.md){target="_blank"}." +!!! tip "We support JSON serializable data, [Python Dataclasses](https://docs.python.org/3.7/library/dataclasses.html){target="_blank" rel="nofollow"}, [Parser/Pydantic Models](parser.md){target="_blank" rel="nofollow"}, and our [Event Source Data Classes](./data_classes.md){target="_blank" rel="nofollow"}." ???+ warning "Limitation" Make sure to call your decorated function using keyword arguments. @@ -154,7 +154,7 @@ When using `idempotent_function`, you must tell us which keyword parameter in yo #### Batch integration -You can can easily integrate with [Batch utility](batch.md){target="_blank"} via context manager. This ensures that you process each record in an idempotent manner, and guard against a [Lambda timeout](#lambda-timeouts) idempotent situation. +You can can easily integrate with [Batch utility](batch.md){target="_blank" rel="nofollow"} via context manager. This ensures that you process each record in an idempotent manner, and guard against a [Lambda timeout](#lambda-timeouts) idempotent situation. ???+ "Choosing an unique batch record attribute" In this example, we choose `messageId` as our idempotency key since we know it'll be unique. @@ -193,7 +193,7 @@ If we were to treat the entire request as our idempotency key, a simple HTTP hea The payload extracted by the `event_key_jmespath` is treated as a string by default. This means there could be differences in whitespace even when the JSON payload itself is identical. - To alter this behaviour, we can use the [JMESPath built-in function](jmespath_functions.md#powertools_json-function){target="_blank"} `powertools_json()` to treat the payload as a JSON object (dict) rather than a string. + To alter this behaviour, we can use the [JMESPath built-in function](jmespath_functions.md#powertools_json-function){target="_blank" rel="nofollow"} `powertools_json()` to treat the payload as a JSON object (dict) rather than a string. === "Payment function" @@ -212,7 +212,7 @@ If we were to treat the entire request as our idempotency key, a simple HTTP hea ???+ note This is automatically done when you decorate your Lambda handler with [@idempotent decorator](#idempotent-decorator). -To prevent against extended failed retries when a [Lambda function times out](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/){target="_blank"}, +To prevent against extended failed retries when a [Lambda function times out](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/){target="_blank" rel="nofollow"}, Powertools for AWS Lambda (Python) calculates and includes the remaining invocation available time as part of the idempotency record. ???+ example @@ -498,13 +498,13 @@ Idempotent decorator can be further configured with **`IdempotencyConfig`** as s | Parameter | Default | Description | | ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **event_key_jmespath** | `""` | JMESPath expression to extract the idempotency key from the event record using [built-in functions](/utilities/jmespath_functions){target="_blank"} | +| **event_key_jmespath** | `""` | JMESPath expression to extract the idempotency key from the event record using [built-in functions](/utilities/jmespath_functions){target="_blank" rel="nofollow"} | | **payload_validation_jmespath** | `""` | JMESPath expression to validate whether certain parameters have changed in the event while the event payload | | **raise_on_no_idempotency_key** | `False` | Raise exception if no idempotency key was found in the request | | **expires_after_seconds** | 3600 | The number of seconds to wait before a record is expired | | **use_local_cache** | `False` | Whether to locally cache idempotency results | | **local_cache_max_items** | 256 | Max number of items to store in local cache | -| **hash_function** | `md5` | Function to use for calculating hashes, as provided by [hashlib](https://docs.python.org/3/library/hashlib.html){target="_blank"} in the standard library. | +| **hash_function** | `md5` | Function to use for calculating hashes, as provided by [hashlib](https://docs.python.org/3/library/hashlib.html){target="_blank" rel="nofollow"} in the standard library. | ### Handling concurrent executions with the same payload @@ -561,7 +561,7 @@ You can change this window with the **`expires_after_seconds`** parameter: This will mark any records older than 5 minutes as expired, and [your function will be executed as normal if it is invoked with a matching payload](#expired-idempotency-records). ???+ important "Idempotency record expiration vs DynamoDB time-to-live (TTL)" - [DynamoDB TTL is a feature](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html){target="_blank"} to remove items after a certain period of time, it may occur within 48 hours of expiration. + [DynamoDB TTL is a feature](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html){target="_blank" rel="nofollow"} to remove items after a certain period of time, it may occur within 48 hours of expiration. We don't rely on DynamoDB or any persistence storage layer to determine whether a record is expired to avoid eventual inconsistency states. @@ -635,8 +635,8 @@ This means that we will raise **`IdempotencyKeyError`** if the evaluation of **` ``` ### Customizing boto configuration - -The **`boto_config`** and **`boto3_session`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank"} or a custom [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank"} when constructing the persistence store. + +The **`boto_config`** and **`boto3_session`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank" rel="nofollow"} or a custom [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank" rel="nofollow"} when constructing the persistence store. === "Custom session" @@ -744,7 +744,7 @@ The idempotency utility provides several routes to test your code. ### Disabling the idempotency utility When testing your code, you may wish to disable the idempotency logic altogether and focus on testing your business logic. To do this, you can set the environment variable `POWERTOOLS_IDEMPOTENCY_DISABLED` -with a truthy value. If you prefer setting this for specific tests, and are using Pytest, you can use [monkeypatch](https://docs.pytest.org/en/latest/monkeypatch.html){target="_blank"} fixture: +with a truthy value. If you prefer setting this for specific tests, and are using Pytest, you can use [monkeypatch](https://docs.pytest.org/en/latest/monkeypatch.html){target="_blank" rel="nofollow"} fixture: === "test_disabling_idempotency_utility.py" @@ -760,7 +760,7 @@ with a truthy value. If you prefer setting this for specific tests, and are usin ### Testing with DynamoDB Local -To test with [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html){target="_blank"}, you can replace the `DynamoDB client` used by the persistence layer with one you create inside your tests. This allows you to set the endpoint_url. +To test with [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html){target="_blank" rel="nofollow"}, you can replace the `DynamoDB client` used by the persistence layer with one you create inside your tests. This allows you to set the endpoint_url. === "test_with_dynamodb_local.py" @@ -776,7 +776,7 @@ To test with [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/ ### How do I mock all DynamoDB I/O operations -The idempotency utility lazily creates the dynamodb [Table](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank"} which it uses to access DynamoDB. +The idempotency utility lazily creates the dynamodb [Table](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank" rel="nofollow"} which it uses to access DynamoDB. This means it is possible to pass a mocked Table resource, or stub various methods. === "test_with_io_operations.py" @@ -794,4 +794,4 @@ This means it is possible to pass a mocked Table resource, or stub various metho ## Extra resources If you're interested in a deep dive on how Amazon uses idempotency when building our APIs, check out -[this article](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/){target="_blank"}. +[this article](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/){target="_blank" rel="nofollow"}. diff --git a/docs/utilities/jmespath_functions.md b/docs/utilities/jmespath_functions.md index 41b6b240adc..ae1c40c35e1 100644 --- a/docs/utilities/jmespath_functions.md +++ b/docs/utilities/jmespath_functions.md @@ -8,7 +8,7 @@ description: Utility ???+ tip JMESPath is a query language for JSON used by AWS CLI, AWS Python SDK, and Powertools for AWS Lambda (Python). -Built-in [JMESPath](https://jmespath.org/){target="_blank"} Functions to easily deserialize common encoded JSON payloads in Lambda functions. +Built-in [JMESPath](https://jmespath.org/){target="_blank" rel="nofollow"} Functions to easily deserialize common encoded JSON payloads in Lambda functions. ## Key features @@ -19,18 +19,18 @@ Built-in [JMESPath](https://jmespath.org/){target="_blank"} Functions to easily ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. You might have events that contains encoded JSON payloads as string, base64, or even in compressed format. It is a common use case to decode and extract them partially or fully as part of your Lambda function invocation. -Powertools for AWS Lambda (Python) also have utilities like [validation](validation.md){target="_blank"}, [idempotency](idempotency.md){target="_blank"}, or [feature flags](feature_flags.md){target="_blank"} where you might need to extract a portion of your data before using them. +Powertools for AWS Lambda (Python) also have utilities like [validation](validation.md){target="_blank" rel="nofollow"}, [idempotency](idempotency.md){target="_blank" rel="nofollow"}, or [feature flags](feature_flags.md){target="_blank" rel="nofollow"} where you might need to extract a portion of your data before using them. ???+ info "Terminology" **Envelope** is the terminology we use for the **JMESPath expression** to extract your JSON object from your data input. We might use those two terms interchangeably. ### Extracting data -You can use the `extract_data_from_envelope` function with any [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank"}. +You can use the `extract_data_from_envelope` function with any [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank" rel="nofollow"}. ???+ tip Another common use case is to fetch deeply nested data, filter, flatten, and more. @@ -120,7 +120,7 @@ This sample will deserialize the JSON string within the `data` key before valida > **Idempotency scenario** -This sample will deserialize the JSON string within the `body` key before [Idempotency](./idempotency.md){target="_blank"} processes it. +This sample will deserialize the JSON string within the `body` key before [Idempotency](./idempotency.md){target="_blank" rel="nofollow"} processes it. === "powertools_json_idempotency_jmespath.py" @@ -187,9 +187,9 @@ This sample will decompress and decode base64 data from Cloudwatch Logs, then us ???+ warning This should only be used for advanced use cases where you have special formats not covered by the built-in functions. -For special binary formats that you want to decode before applying JSON Schema validation, you can bring your own [JMESPath function](https://github.com/jmespath/jmespath.py#custom-functions){target="_blank"} and any additional option via `jmespath_options` param. To keep Powertools for AWS Lambda (Python) built-in functions, you can subclass from `PowertoolsFunctions`. +For special binary formats that you want to decode before applying JSON Schema validation, you can bring your own [JMESPath function](https://github.com/jmespath/jmespath.py#custom-functions){target="_blank" rel="nofollow"} and any additional option via `jmespath_options` param. To keep Powertools for AWS Lambda (Python) built-in functions, you can subclass from `PowertoolsFunctions`. -Here is an example of how to decompress messages using [zlib](https://docs.python.org/3/library/zlib.html){target="_blank"}: +Here is an example of how to decompress messages using [zlib](https://docs.python.org/3/library/zlib.html){target="_blank" rel="nofollow"}: === "powertools_custom_jmespath_function.py" diff --git a/docs/utilities/middleware_factory.md b/docs/utilities/middleware_factory.md index c726d939e0a..9ff3a6fb9c7 100644 --- a/docs/utilities/middleware_factory.md +++ b/docs/utilities/middleware_factory.md @@ -15,7 +15,7 @@ Middleware factory provides a decorator factory to create your own middleware to ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. You might need a custom middleware to abstract non-functional code. These are often custom authorization or any reusable logic you might need to run before/after a Lambda function invocation. @@ -70,7 +70,7 @@ You can also have your own keyword arguments after the mandatory arguments. ## Advanced -For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target="_blank"} inside your middleware, and add annotations as well as metadata for additional operational insights. +For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target="_blank" rel="nofollow"} inside your middleware, and add annotations as well as metadata for additional operational insights. === "advanced_middleware_tracer_function.py" ```python hl_lines="7 9 12 16 17 19 25 42" @@ -87,12 +87,12 @@ For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target=" ### Tracing middleware **execution** -If you are making use of [Tracer](../core/tracer.md){target="_blank"}, you can trace the execution of your middleware to ease operations. +If you are making use of [Tracer](../core/tracer.md){target="_blank" rel="nofollow"}, you can trace the execution of your middleware to ease operations. This makes use of an existing Tracer instance that you may have initialized anywhere in your code. ???+ warning - You must [enable Active Tracing](../core/tracer/#permissions){target="_blank"} in your Lambda function when using this feature, otherwise Lambda cannot send traces to XRay. + You must [enable Active Tracing](../core/tracer/#permissions){target="_blank" rel="nofollow"} in your Lambda function when using this feature, otherwise Lambda cannot send traces to XRay. === "getting_started_middleware_tracer_function.py" ```python hl_lines="8 14 15 36" @@ -105,14 +105,14 @@ This makes use of an existing Tracer instance that you may have initialized anyw --8<-- "examples/middleware_factory/src/getting_started_middleware_tracer_payload.json" ``` -When executed, your middleware name will [appear in AWS X-Ray Trace details as](../core/tracer.md){target="_blank"} `## middleware_name`, in this example the middleware name is `## middleware_with_tracing`. +When executed, your middleware name will [appear in AWS X-Ray Trace details as](../core/tracer.md){target="_blank" rel="nofollow"} `## middleware_name`, in this example the middleware name is `## middleware_with_tracing`. ![Middleware simple Tracer](../media/middleware_factory_tracer_1.png) ### Combining Powertools for AWS Lambda (Python) utilities -You can create your own middleware and combine many features of Powertools for AWS Lambda (Python) such as [trace](../core/logger.md){target="_blank"}, [logs](../core/logger.md){target="_blank"}, [feature flags](feature_flags.md){target="_blank"}, [validation](validation.md){target="_blank"}, [jmespath_functions](jmespath_functions.md){target="_blank"} and others to abstract non-functional code. +You can create your own middleware and combine many features of Powertools for AWS Lambda (Python) such as [trace](../core/logger.md){target="_blank" rel="nofollow"}, [logs](../core/logger.md){target="_blank" rel="nofollow"}, [feature flags](feature_flags.md){target="_blank" rel="nofollow"}, [validation](validation.md){target="_blank" rel="nofollow"}, [jmespath_functions](jmespath_functions.md){target="_blank" rel="nofollow"} and others to abstract non-functional code. In the example below, we create a Middleware with the following features: @@ -147,5 +147,5 @@ In the example below, we create a Middleware with the following features: * Use `trace_execution` to quickly understand the performance impact of your middlewares, and reduce or merge tasks when necessary * When nesting multiple middlewares, always return the handler with event and context, or response -* Keep in mind [Python decorators execution order](https://realpython.com/primer-on-python-decorators/#nesting-decorators){target="_blank"}. Lambda handler is actually called once (top-down) +* Keep in mind [Python decorators execution order](https://realpython.com/primer-on-python-decorators/#nesting-decorators){target="_blank" rel="nofollow"}. Lambda handler is actually called once (top-down) * Async middlewares are not supported diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index 97a7ab3156d..867939da3f1 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -4,7 +4,7 @@ description: Utility --- -The parameters utility provides high-level functions to retrieve one or multiple parameter values from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html){target="_blank"}, [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/){target="_blank"}, [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank"}, [Amazon DynamoDB](https://aws.amazon.com/dynamodb/){target="_blank"}, or bring your own. +The parameters utility provides high-level functions to retrieve one or multiple parameter values from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html){target="_blank" rel="nofollow"}, [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/){target="_blank" rel="nofollow"}, [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank" rel="nofollow"}, [Amazon DynamoDB](https://aws.amazon.com/dynamodb/){target="_blank" rel="nofollow"}, or bring your own. ## Key features @@ -16,7 +16,7 @@ The parameters utility provides high-level functions to retrieve one or multiple ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. By default, we fetch parameters from System Manager Parameter Store, secrets from Secrets Manager, and application configuration from AppConfig. @@ -304,7 +304,7 @@ You can create your own custom parameter store provider by inheriting the `BaseP All transformation and caching logic is handled by the `get()` and `get_multiple()` methods from the base provider class. -Here are two examples of implementing a custom parameter store. One using an external service like [Hashicorp Vault](https://www.vaultproject.io/){target="_blank"}, a widely popular key-value and secret storage and the other one using [Amazon S3](https://aws.amazon.com/s3/?nc1=h_ls){target="_blank"}, a popular object storage. +Here are two examples of implementing a custom parameter store. One using an external service like [Hashicorp Vault](https://www.vaultproject.io/){target="_blank" rel="nofollow"}, a widely popular key-value and secret storage and the other one using [Amazon S3](https://aws.amazon.com/s3/?nc1=h_ls){target="_blank" rel="nofollow"}, a popular object storage. === "working_with_own_provider_vault.py" ```python hl_lines="5 13 20 24" @@ -399,15 +399,15 @@ Here is the mapping between this utility's functions and methods and the underly | Provider | Function/Method | Client name | Function name | | ------------------- | ------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| SSM Parameter Store | `get_parameter` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank"} | -| SSM Parameter Store | `get_parameters` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank"} | -| SSM Parameter Store | `SSMProvider.get` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank"} | -| SSM Parameter Store | `SSMProvider.get_multiple` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank"} | -| Secrets Manager | `get_secret` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank"} | -| Secrets Manager | `SecretsProvider.get` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank"} | -| DynamoDB | `DynamoDBProvider.get` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank"}) | [get_item](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.get_item) | -| DynamoDB | `DynamoDBProvider.get_multiple` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank"}) | [query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.query) | -| App Config | `get_app_config` | `appconfigdata` | [start_configuration_session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.start_configuration_session){target="_blank"} and [get_latest_configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.get_latest_configuration){target="_blank"} | +| SSM Parameter Store | `get_parameter` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank" rel="nofollow"} | +| SSM Parameter Store | `get_parameters` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank" rel="nofollow"} | +| SSM Parameter Store | `SSMProvider.get` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank" rel="nofollow"} | +| SSM Parameter Store | `SSMProvider.get_multiple` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank" rel="nofollow"} | +| Secrets Manager | `get_secret` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank" rel="nofollow"} | +| Secrets Manager | `SecretsProvider.get` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank" rel="nofollow"} | +| DynamoDB | `DynamoDBProvider.get` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank" rel="nofollow"}) | [get_item](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.get_item) | +| DynamoDB | `DynamoDBProvider.get_multiple` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank" rel="nofollow"}) | [query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.query) | +| App Config | `get_app_config` | `appconfigdata` | [start_configuration_session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.start_configuration_session){target="_blank" rel="nofollow"} and [get_latest_configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.get_latest_configuration){target="_blank" rel="nofollow"} | ### Bring your own boto client @@ -432,7 +432,7 @@ Bringing them together in a single code snippet would look like this: ### Customizing boto configuration -The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank"}, [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank"}, or a [boto3 client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/boto3.html){target="_blank"} when constructing any of the built-in provider classes. +The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank" rel="nofollow"}, [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank" rel="nofollow"}, or a [boto3 client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/boto3.html){target="_blank" rel="nofollow"} when constructing any of the built-in provider classes. ???+ tip You can use a custom session for retrieving parameters cross-account/region and for snapshot testing. @@ -458,7 +458,7 @@ The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enabl ### Mocking parameter values -For unit testing your applications, you can mock the calls to the parameters utility to avoid calling AWS APIs. This can be achieved in a number of ways - in this example, we use the [pytest monkeypatch fixture](https://docs.pytest.org/en/latest/how-to/monkeypatch.html){target="_blank"} to patch the `parameters.get_parameter` method: +For unit testing your applications, you can mock the calls to the parameters utility to avoid calling AWS APIs. This can be achieved in a number of ways - in this example, we use the [pytest monkeypatch fixture](https://docs.pytest.org/en/latest/how-to/monkeypatch.html){target="_blank" rel="nofollow"} to patch the `parameters.get_parameter` method: === "test_single_mock.py" ```python hl_lines="4 8" @@ -478,8 +478,8 @@ If we need to use this pattern across multiple tests, we can avoid repetition by ``` Alternatively, if we need more fully featured mocking (for example checking the arguments passed to `get_parameter`), we -can use [unittest.mock](https://docs.python.org/3/library/unittest.mock.html){target="_blank"} from the python stdlib instead of pytest's `monkeypatch` fixture. In this example, we use the -[patch](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch){target="_blank"} decorator to replace the `aws_lambda_powertools.utilities.parameters.get_parameter` function with a [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock){target="_blank"} +can use [unittest.mock](https://docs.python.org/3/library/unittest.mock.html){target="_blank" rel="nofollow"} from the python stdlib instead of pytest's `monkeypatch` fixture. In this example, we use the +[patch](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch){target="_blank" rel="nofollow"} decorator to replace the `aws_lambda_powertools.utilities.parameters.get_parameter` function with a [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock){target="_blank" rel="nofollow"} object named `get_parameter_mock`. === "test_with_monkeypatch.py" diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index d98835a8381..6abef997a5e 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -4,7 +4,7 @@ description: Utility --- -This utility provides data parsing and deep validation using [Pydantic](https://pydantic-docs.helpmanual.io/){target="_blank"}. +This utility provides data parsing and deep validation using [Pydantic](https://pydantic-docs.helpmanual.io/){target="_blank" rel="nofollow"}. ## Key features @@ -21,7 +21,7 @@ Powertools for AWS Lambda (Python) supports Pydantic v1 and v2. Each Pydantic ve #### Using Pydantic v1 -!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank" rel="nofollow"}" Add `aws-lambda-powertools[parser]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. @@ -29,13 +29,13 @@ Add `aws-lambda-powertools[parser]` as a dependency in your preferred tool: _e.g This will increase the compressed package size by >10MB due to the Pydantic dependency. To reduce the impact on the package size at the expense of 30%-50% of its performance [Pydantic can also be - installed without binary files](https://pydantic-docs.helpmanual.io/install/#performance-vs-package-size-trade-off){target="_blank"}: + installed without binary files](https://pydantic-docs.helpmanual.io/install/#performance-vs-package-size-trade-off){target="_blank" rel="nofollow"}: Pip example: `SKIP_CYTHON=1 pip install --no-binary pydantic aws-lambda-powertools[parser]` #### Using Pydantic v2 -You need to bring Pydantic v2.0.3 or later as an external dependency. Note that [we suppress Pydantic v2 deprecation warnings](https://github.com/aws-powertools/powertools-lambda-python/issues/2672){target="_blank"} to reduce noise and optimize log costs. +You need to bring Pydantic v2.0.3 or later as an external dependency. Note that [we suppress Pydantic v2 deprecation warnings](https://github.com/aws-powertools/powertools-lambda-python/issues/2672){target="_blank" rel="nofollow"} to reduce noise and optimize log costs. Add `aws-lambda-powertools` and `pydantic>=2.0.3` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. @@ -260,13 +260,13 @@ for order_item in ret.detail.items: ???+ tip When extending a `string` field containing JSON, you need to wrap the field - with [Pydantic's Json Type](https://pydantic-docs.helpmanual.io/usage/types/#json-type){target="_blank"}: + with [Pydantic's Json Type](https://pydantic-docs.helpmanual.io/usage/types/#json-type){target="_blank" rel="nofollow"}: ```python hl_lines="14 18-19" --8<-- "examples/parser/src/extending_built_in_models_with_json_mypy.py" ``` - Alternatively, you could use a [Pydantic validator](https://pydantic-docs.helpmanual.io/usage/validators/){target="_blank"} to transform the JSON string into a dict before the mapping: + Alternatively, you could use a [Pydantic validator](https://pydantic-docs.helpmanual.io/usage/validators/){target="_blank" rel="nofollow"} to transform the JSON string into a dict before the mapping: ```python hl_lines="18-20 24-25" --8<-- "examples/parser/src/extending_built_in_models_with_json_validator.py" @@ -511,14 +511,14 @@ parse(model=UserModel, event=payload) ### Advanced use cases ???+ tip "Tip: Looking to auto-generate models from JSON, YAML, JSON Schemas, OpenApi, etc?" - Use Koudai Aono's [data model code generation tool for Pydantic](https://github.com/koxudaxi/datamodel-code-generator){target="_blank"} + Use Koudai Aono's [data model code generation tool for Pydantic](https://github.com/koxudaxi/datamodel-code-generator){target="_blank" rel="nofollow"} -There are number of advanced use cases well documented in Pydantic's doc such as creating [immutable models](https://pydantic-docs.helpmanual.io/usage/models/#faux-immutability){target="_blank"}, [declaring fields with dynamic values](https://pydantic-docs.helpmanual.io/usage/models/#field-with-dynamic-default-value){target="_blank"}. +There are number of advanced use cases well documented in Pydantic's doc such as creating [immutable models](https://pydantic-docs.helpmanual.io/usage/models/#faux-immutability){target="_blank" rel="nofollow"}, [declaring fields with dynamic values](https://pydantic-docs.helpmanual.io/usage/models/#field-with-dynamic-default-value){target="_blank" rel="nofollow"}. ???+ tip "Pydantic helper functions" - Pydantic also offers [functions](https://pydantic-docs.helpmanual.io/usage/models/#helper-functions){target="_blank"} to parse models from files, dicts, string, etc. + Pydantic also offers [functions](https://pydantic-docs.helpmanual.io/usage/models/#helper-functions){target="_blank" rel="nofollow"} to parse models from files, dicts, string, etc. -Two possible unknown use cases are Models and exception' serialization. Models have methods to [export them](https://pydantic-docs.helpmanual.io/usage/exporting_models/){target="_blank"} as `dict`, `JSON`, `JSON Schema`, and Validation exceptions can be exported as JSON. +Two possible unknown use cases are Models and exception' serialization. Models have methods to [export them](https://pydantic-docs.helpmanual.io/usage/exporting_models/){target="_blank" rel="nofollow"} as `dict`, `JSON`, `JSON Schema`, and Validation exceptions can be exported as JSON. ```python hl_lines="21 28-31" title="Converting data models in various formats" from aws_lambda_powertools.utilities import Logger diff --git a/docs/utilities/streaming.md b/docs/utilities/streaming.md index c89c0cf8b86..5c43bb8bc9b 100644 --- a/docs/utilities/streaming.md +++ b/docs/utilities/streaming.md @@ -87,15 +87,15 @@ We provide popular built-in transformations that you can apply against your stre | Name | Description | Class name | | -------- | ----------------------------------------------------------------------------------------------------------------- | ------------- | -| **Gzip** | Gunzips the stream of data using the [gzip library](https://docs.python.org/3/library/gzip.html){target="_blank"} | GzipTransform | -| **Zip** | Exposes the stream as a [ZipFile object](https://docs.python.org/3/library/zipfile.html){target="_blank"} | ZipTransform | +| **Gzip** | Gunzips the stream of data using the [gzip library](https://docs.python.org/3/library/gzip.html){target="_blank" rel="nofollow"} | GzipTransform | +| **Zip** | Exposes the stream as a [ZipFile object](https://docs.python.org/3/library/zipfile.html){target="_blank" rel="nofollow"} | ZipTransform | | **CSV** | Parses each CSV line as a CSV object, returning dictionary objects | CsvTransform | ## Advanced ### Skipping or reading backwards -`S3Object` implements [Python I/O interface](https://docs.python.org/3/tutorial/inputoutput.html){target="_blank"}. This means you can use `seek` to start reading contents of your file from any particular position, saving you processing time. +`S3Object` implements [Python I/O interface](https://docs.python.org/3/tutorial/inputoutput.html){target="_blank" rel="nofollow"}. This means you can use `seek` to start reading contents of your file from any particular position, saving you processing time. #### Reading backwards @@ -133,9 +133,9 @@ We will propagate additional options to the underlying implementation for each t | Name | Available options | | ----------------- | ------------------------------------------------------------------------------------------------------ | -| **GzipTransform** | [GzipFile constructor](https://docs.python.org/3/library/gzip.html#gzip.GzipFile){target="_blank"} | -| **ZipTransform** | [ZipFile constructor](https://docs.python.org/3/library/zipfile.html#zipfile.ZipFile){target="_blank"} | -| **CsvTransform** | [DictReader constructor](https://docs.python.org/3/library/csv.html#csv.DictReader){target="_blank"} | +| **GzipTransform** | [GzipFile constructor](https://docs.python.org/3/library/gzip.html#gzip.GzipFile){target="_blank" rel="nofollow"} | +| **ZipTransform** | [ZipFile constructor](https://docs.python.org/3/library/zipfile.html#zipfile.ZipFile){target="_blank" rel="nofollow"} | +| **CsvTransform** | [DictReader constructor](https://docs.python.org/3/library/csv.html#csv.DictReader){target="_blank" rel="nofollow"} | For instance, take `ZipTransform`. You can use the `compression` parameter if you want to unzip an S3 object compressed with `LZMA`. @@ -185,6 +185,6 @@ Create an input payload using `io.BytesIO` and assert the response of the transf ### AWS X-Ray segment size limit -We make multiple API calls to S3 as you read chunks from your S3 object. If your function is decorated with [Tracer](./../core/tracer.md){target="_blank"}, you can easily hit [AWS X-Ray 64K segment size](https://docs.aws.amazon.com/general/latest/gr/xray.html#limits_xray){target="_blank"} when processing large files. +We make multiple API calls to S3 as you read chunks from your S3 object. If your function is decorated with [Tracer](./../core/tracer.md){target="_blank" rel="nofollow"}, you can easily hit [AWS X-Ray 64K segment size](https://docs.aws.amazon.com/general/latest/gr/xray.html#limits_xray){target="_blank" rel="nofollow"} when processing large files. !!! tip "Use tracer decorators in parts where you don't read your `S3Object` instead." diff --git a/docs/utilities/typing.md b/docs/utilities/typing.md index 9e2cc5024ab..a76d53ab78a 100644 --- a/docs/utilities/typing.md +++ b/docs/utilities/typing.md @@ -18,9 +18,9 @@ This typing utility provides static typing classes that can be used to ease the ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. -We provide static typing for any context methods or properties implemented by [Lambda context object](https://docs.aws.amazon.com/lambda/latest/dg/python-context.html){target="_blank"}. +We provide static typing for any context methods or properties implemented by [Lambda context object](https://docs.aws.amazon.com/lambda/latest/dg/python-context.html){target="_blank" rel="nofollow"}. ## LambdaContext diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 1eead47a970..7dc009db38d 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -16,23 +16,23 @@ This utility provides JSON Schema validation for events and responses, including ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. You can validate inbound and outbound events using [`validator` decorator](#validator-decorator). You can also use the standalone `validate` function, if you want more control over the validation process such as handling a validation error. ???+ tip "Tip: Using JSON Schemas for the first time?" - Check this [step-by-step tour in the official JSON Schema website](https://json-schema.org/learn/getting-started-step-by-step.html){target="_blank"}. + Check this [step-by-step tour in the official JSON Schema website](https://json-schema.org/learn/getting-started-step-by-step.html){target="_blank" rel="nofollow"}. - We support any JSONSchema draft supported by [fastjsonschema](https://horejsek.github.io/python-fastjsonschema/){target="_blank"} library. + We support any JSONSchema draft supported by [fastjsonschema](https://horejsek.github.io/python-fastjsonschema/){target="_blank" rel="nofollow"} library. ???+ warning Both `validator` decorator and `validate` standalone function expects your JSON Schema to be a **dictionary**, not a filename. ### Install -!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank" rel="nofollow"}" Add `aws-lambda-powertools[validation]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Validation. @@ -91,7 +91,7 @@ You can also gracefully handle schema validation errors by catching `SchemaValid You might want to validate only a portion of your event - This is what the `envelope` parameter is for. -Envelopes are [JMESPath expressions](https://jmespath.org/tutorial.html){target="_blank"} to extract a portion of JSON you want before applying JSON Schema validation. +Envelopes are [JMESPath expressions](https://jmespath.org/tutorial.html){target="_blank" rel="nofollow"} to extract a portion of JSON you want before applying JSON Schema validation. Here is a sample custom EventBridge event, where we only validate what's inside the `detail` key: @@ -112,8 +112,8 @@ Here is a sample custom EventBridge event, where we only validate what's inside ```json --8<-- "examples/validation/src/getting_started_validator_unwrapping_payload.json" ``` - -This is quite powerful because you can use JMESPath Query language to extract records from [arrays](https://jmespath.org/tutorial.html#list-and-slice-projections){target="_blank"}, combine [pipe](https://jmespath.org/tutorial.html#pipe-expressions){target="_blank"} and [function expressions](https://jmespath.org/tutorial.html#functions){target="_blank"}. + +This is quite powerful because you can use JMESPath Query language to extract records from [arrays](https://jmespath.org/tutorial.html#list-and-slice-projections){target="_blank" rel="nofollow"}, combine [pipe](https://jmespath.org/tutorial.html#pipe-expressions){target="_blank" rel="nofollow"} and [function expressions](https://jmespath.org/tutorial.html#functions){target="_blank" rel="nofollow"}. When combined, these features allow you to extract what you need before validating the actual payload. @@ -157,7 +157,7 @@ Here is a handy table with built-in envelopes along with their JMESPath expressi ### Validating custom formats ???+ note - JSON Schema DRAFT 7 [has many new built-in formats](https://json-schema.org/understanding-json-schema/reference/string.html#format){target="_blank"} such as date, time, and specifically a regex format which might be a better replacement for a custom format, if you do have control over the schema. + JSON Schema DRAFT 7 [has many new built-in formats](https://json-schema.org/understanding-json-schema/reference/string.html#format){target="_blank" rel="nofollow"} such as date, time, and specifically a regex format which might be a better replacement for a custom format, if you do have control over the schema. JSON Schemas with custom formats like `awsaccountid` will fail validation. If you have these, you can pass them using `formats` parameter: @@ -193,8 +193,8 @@ For each format defined in a dictionary key, you must use a regex, or a function ### Built-in JMESPath functions You might have events or responses that contain non-encoded JSON, where you need to decode before validating them. - -You can use our built-in [JMESPath functions](./jmespath_functions.md){target="_blank"} within your expressions to do exactly that to [deserialize JSON Strings](./jmespath_functions.md#powertools_json-function){target="_blank"}, [decode base64](./jmespath_functions.md#powertools_base64-function){target="_blank"}, and [decompress gzip data](./jmespath_functions.md#powertools_base64_gzip-function){target="_blank"}. + +You can use our built-in [JMESPath functions](./jmespath_functions.md){target="_blank" rel="nofollow"} within your expressions to do exactly that to [deserialize JSON Strings](./jmespath_functions.md#powertools_json-function){target="_blank" rel="nofollow"}, [decode base64](./jmespath_functions.md#powertools_base64-function){target="_blank" rel="nofollow"}, and [decompress gzip data](./jmespath_functions.md#powertools_base64_gzip-function){target="_blank" rel="nofollow"}. ???+ info We use these for [built-in envelopes](#built-in-envelopes) to easily to decode and unwrap events from sources like Kinesis, CloudWatch Logs, etc. diff --git a/docs/we_made_this.md b/docs/we_made_this.md index 3f3257f40e5..a2f3d0e8022 100644 --- a/docs/we_made_this.md +++ b/docs/we_made_this.md @@ -7,19 +7,19 @@ description: Blog posts, tutorials, and videos about Powertools for AWS Lambda ( This space is dedicated to highlight our awesome community content featuring Powertools for AWS Lambda (Python) 🙏! -!!! info "[Get your content featured here](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank"}!" +!!! info "[Get your content featured here](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank" rel="nofollow"}!" ## Connect -[![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET){target="_blank"} +[![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET){target="_blank" rel="nofollow"} -Join us on [Discord](https://discord.gg/B8zZKbbyET){target="_blank"} to connect with the Powertools for AWS Lambda (Python) community 👋. Ask questions, learn from each other, contribute, hang out with key contributors, and more! +Join us on [Discord](https://discord.gg/B8zZKbbyET){target="_blank" rel="nofollow"} to connect with the Powertools for AWS Lambda (Python) community 👋. Ask questions, learn from each other, contribute, hang out with key contributors, and more! ## Blog posts ### AWS Lambda Cookbook — Following best practices with Lambda Powertools -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank" rel="nofollow"}** A collection of articles explaining in detail how Lambda Powertools helps with a Serverless adoption strategy and its challenges. @@ -41,66 +41,66 @@ A collection of articles explaining in detail how Lambda Powertools helps with a ### Making all your APIs idempotent -> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank"}** :material-twitter: +> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank" rel="nofollow"}** :material-twitter: This article dives into what idempotency means for APIs, their use cases, and how to implement them. -* [blog.walmsles.io/making-all-your-apis-idempotent](https://blog.walmsles.io/making-all-your-apis-idempotent){target="_blank"} +* [blog.walmsles.io/making-all-your-apis-idempotent](https://blog.walmsles.io/making-all-your-apis-idempotent){target="_blank" rel="nofollow"} ### Deep dive on Lambda Powertools Idempotency feature -> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank"}** :material-twitter: +> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank" rel="nofollow"}** :material-twitter: This article describes how to best calculate your idempotency token, implementation details, and how to handle idempotency in RESTful APIs. -* [blog.walmsles.io/aws-lambda-powertools-idempotency-a-deeper-dive](https://blog.walmsles.io/aws-lambda-powertools-idempotency-a-deeper-dive){target="_blank"} +* [blog.walmsles.io/aws-lambda-powertools-idempotency-a-deeper-dive](https://blog.walmsles.io/aws-lambda-powertools-idempotency-a-deeper-dive){target="_blank" rel="nofollow"} ### Developing AWS Lambda functions with AWS Lambda Powertools -> **Author: [Stephan Huber](https://linkedin.com/in/sthuber90){target="_blank"}** :material-linkedin: +> **Author: [Stephan Huber](https://linkedin.com/in/sthuber90){target="_blank" rel="nofollow"}** :material-linkedin: This article walks through how to add Powertools to an existing project, covers Tracer, Logger, Metrics, and JSON Schema Validation. -* [globaldatanet.com/tech-blog/develop-lambda-functions-with-aws-lambda-powertools](https://globaldatanet.com/tech-blog/develop-lambda-functions-with-aws-lambda-powertools){target="_blank"} +* [globaldatanet.com/tech-blog/develop-lambda-functions-with-aws-lambda-powertools](https://globaldatanet.com/tech-blog/develop-lambda-functions-with-aws-lambda-powertools){target="_blank" rel="nofollow"} ### Speed-up event-driven projects -> **Author: [Joris Conijn](https://www.linkedin.com/in/jorisconijn){target="_blank"}** :material-linkedin: +> **Author: [Joris Conijn](https://www.linkedin.com/in/jorisconijn){target="_blank" rel="nofollow"}** :material-linkedin: This article walks through a sample AWS EventBridge cookiecutter template presented at the AWS Community Day Netherlands 2022. -* [binx.io/2022/10/11/speedup-event-driven-projects/](https://binx.io/2022/10/11/speedup-event-driven-projects/){target="_blank"} -* [Slides](https://www.slideshare.net/JorisConijn/let-codecommit-work-for-you){target="_blank"} +* [binx.io/2022/10/11/speedup-event-driven-projects/](https://binx.io/2022/10/11/speedup-event-driven-projects/){target="_blank" rel="nofollow"} +* [Slides](https://www.slideshare.net/JorisConijn/let-codecommit-work-for-you){target="_blank" rel="nofollow"} ### Implementing Feature Flags with AWS AppConfig and AWS Lambda Powertools -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank" rel="nofollow"}** This article walks through how CyberArk uses Powertools to implement Feature Flags with AWS AppConfig -* [aws.amazon.com/blogs/mt/how-cyberark-implements-feature-flags-with-aws-appconfig](https://aws.amazon.com/blogs/mt/how-cyberark-implements-feature-flags-with-aws-appconfig){target="_blank"} +* [aws.amazon.com/blogs/mt/how-cyberark-implements-feature-flags-with-aws-appconfig](https://aws.amazon.com/blogs/mt/how-cyberark-implements-feature-flags-with-aws-appconfig){target="_blank" rel="nofollow"} ### Designing for Idempotency -> **Author: [Valentin Dreismann](linkedin.com/in/valentin-dreismann-69694b16a){target="_blank"}** :material-linkedin: +> **Author: [Valentin Dreismann](linkedin.com/in/valentin-dreismann-69694b16a){target="_blank" rel="nofollow"}** :material-linkedin: This article outlines the importance of idempotency, key considerations and trade-offs when implementing in your systems. -* [Idempotency the right way](https://engineering.cloudflight.io/idempotency-the-right-way){target="_blank"} +* [Idempotency the right way](https://engineering.cloudflight.io/idempotency-the-right-way){target="_blank" rel="nofollow"} ### Implementing Idempotency in Serverless Architectures -> **Author: [Seongwoo Choi](https://www.linkedin.com/in/%EC%84%B1%EC%9A%B0-%EC%B5%9C-44b12b1ab/){target="_blank"}** :material-linkedin: +> **Author: [Seongwoo Choi](https://www.linkedin.com/in/%EC%84%B1%EC%9A%B0-%EC%B5%9C-44b12b1ab/){target="_blank" rel="nofollow"}** :material-linkedin: This blog post focuses on the importance of idempotency in distributed services and explores streamlined idempotent request flows. It provides guidance on idempotency tests using duplicate requests. -* [Implementing Idempotency in Serverless Architectures](https://medium.com/@nuatmochoi/implementing-idempotency-in-serverless-architectures-f9079ef1c7da){target="_blank"} +* [Implementing Idempotency in Serverless Architectures](https://medium.com/@nuatmochoi/implementing-idempotency-in-serverless-architectures-f9079ef1c7da){target="_blank" rel="nofollow"} ## Videos #### Building a resilient input handling with Parser -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank" rel="nofollow"}** When building applications with AWS Lambda it is critical to verify the data structure and validate the input due to the multiple different sources that can trigger them. In this session Ran Isenberg (CyberArk) will present one of the interesting features of AWS Lambda Powertools for python: the parser. @@ -110,15 +110,15 @@ In this session you will learn how to increase code quality, extensibility and t #### Talk DEV to me | Feature Flags with AWS Lambda Powertools -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank" rel="nofollow"}** -A deep dive in the [Feature Flags](./utilities/feature_flags.md){target="_blank"} feature along with tips and tricks. +A deep dive in the [Feature Flags](./utilities/feature_flags.md){target="_blank" rel="nofollow"} feature along with tips and tricks. #### Level Up Your CI/CD With Smart AWS Feature Flags -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank" rel="nofollow"}** Feature flags can improve your CI/CD process by enabling capabilities otherwise not possible, thus making them an enabler of DevOps and a crucial part of continuous integration. Partial rollouts, A/B testing, and the ability to quickly change a configuration without redeploying code are advantages you gain by using features flags. @@ -130,13 +130,13 @@ In this talk, you will learn the added value of using feature flags as part of y ### Introduction to Lambda Powertools -> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank"}** :material-twitter: +> **Author: [Michael Walmsley](https://twitter.com/walmsles){target="_blank" rel="nofollow"}** :material-twitter: This repo contains documentation for a live coding workshop for the AWS Programming and Tools Meetup in Melbourne. The workshop will start with the SAM Cli "Hello World" example API project. Throughout the labs we will introduce each of the AWS Lambda Powertools Core utilities to showcase how simple they are to use and adopt for all your projects, and how powerful they are at bringing you closer to the Well Architected Serverless Lens. -* :material-github: [github.com/walmsles/lambda-powertools-coding-workshop](https://github.com/walmsles/lambda-powertools-coding-workshop){target="_blank"} +* :material-github: [github.com/walmsles/lambda-powertools-coding-workshop](https://github.com/walmsles/lambda-powertools-coding-workshop){target="_blank" rel="nofollow"} **Walk-through video** @@ -146,9 +146,9 @@ Throughout the labs we will introduce each of the AWS Lambda Powertools Core uti ### Complete Lambda Handler Cookbook -> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank"}** +> **Author: [Ran Isenberg](mailto:ran.isenberg@ranthebuilder.cloud) [:material-twitter:](https://twitter.com/IsenbergRan){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/ranisenberg/){target="_blank" rel="nofollow"}** -This repository provides a working, deployable, open source based, AWS Lambda handler and [AWS CDK](https://aws.amazon.com/cdk/){target="_blank"} Python code. +This repository provides a working, deployable, open source based, AWS Lambda handler and [AWS CDK](https://aws.amazon.com/cdk/){target="_blank" rel="nofollow"} Python code. This handler embodies Serverless best practices and has all the bells and whistles for a proper production ready handler. It uses many of the AWS Lambda Powertools utilities for Python. @@ -156,7 +156,7 @@ This handler embodies Serverless best practices and has all the bells and whistl ### Serverless Transactional Message App -> **Author: [Santiago Garcia Arango](mailto:san99tiago@gmail.com) [:material-web:](https://san99tiago.com/){target="_blank"} [:material-linkedin:](https://www.linkedin.com/in/san99tiago/){target="_blank"}** +> **Author: [Santiago Garcia Arango](mailto:san99tiago@gmail.com) [:material-web:](https://san99tiago.com/){target="_blank" rel="nofollow"} [:material-linkedin:](https://www.linkedin.com/in/san99tiago/){target="_blank" rel="nofollow"}** This repository contains a well documented example of a Transactional Messages App that illustrates how to use Lambda PowerTools to process SQS messages in batches (with IaC on top of CDK). From 7dbdd81ad5721f433efadd913ba82bece601faa6 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 26 Jul 2023 15:15:18 +0200 Subject: [PATCH 09/92] fix(logger): strip xray_trace_id when explicitly disabled (#2852) --- aws_lambda_powertools/logging/formatter.py | 8 +++++-- .../test_logger_powertools_formatter.py | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/logging/formatter.py b/aws_lambda_powertools/logging/formatter.py index 03b290fde64..3a7ede4ce4e 100644 --- a/aws_lambda_powertools/logging/formatter.py +++ b/aws_lambda_powertools/logging/formatter.py @@ -236,8 +236,12 @@ def _build_default_keys(): "timestamp": "%(asctime)s", } - @staticmethod - def _get_latest_trace_id(): + def _get_latest_trace_id(self): + xray_trace_id_key = self.log_format.get("xray_trace_id", "") + if xray_trace_id_key is None: + # key is explicitly disabled; ignore it. e.g., Logger(xray_trace_id=None) + return None + xray_trace_id = os.getenv(constants.XRAY_TRACE_ID_ENV) return xray_trace_id.split(";")[0].replace("Root=", "") if xray_trace_id else None diff --git a/tests/functional/test_logger_powertools_formatter.py b/tests/functional/test_logger_powertools_formatter.py index 8b874894e27..61c3f76efd4 100644 --- a/tests/functional/test_logger_powertools_formatter.py +++ b/tests/functional/test_logger_powertools_formatter.py @@ -251,6 +251,27 @@ def test_log_dict_xray_is_updated_when_tracing_id_changes(stdout, monkeypatch, s monkeypatch.delenv(name="_X_AMZN_TRACE_ID") +def test_log_dict_xray_is_not_present_when_explicitly_disabled( + stdout: io.StringIO, + monkeypatch: pytest.MonkeyPatch, + service_name: str, +): + # GIVEN a logger is initialized within a Lambda function with X-Ray enabled + # and X-Ray Trace ID key is explicitly disabled + trace_id = "1-5759e988-bd862e3fe1be46a994272793" + trace_header = f"Root={trace_id};Parent=53995c3f42cd8ad8;Sampled=1" + monkeypatch.setenv(name="_X_AMZN_TRACE_ID", value=trace_header) + logger = Logger(service=service_name, stream=stdout, xray_trace_id=None) + + # WHEN logging a message + logger.info("foo") + + log_dict: dict = json.loads(stdout.getvalue()) + + # THEN `xray_trace_id`` key should not be present + assert "xray_trace_id" not in log_dict + + def test_log_custom_std_log_attribute(stdout, service_name): # GIVEN a logger where we have a standard log attr process # https://docs.python.org/3/library/logging.html#logrecord-attributes From 192343809fe4c428ce3d25c9aef02b404d4c653d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 23:15:26 +0100 Subject: [PATCH 10/92] chore(deps-dev): bump cfn-lint from 0.78.2 to 0.79.3 (#2854) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index cb45c697404..b5e901ac2b2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -365,13 +365,13 @@ files = [ [[package]] name = "cfn-lint" -version = "0.78.2" +version = "0.79.3" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "cfn-lint-0.78.2.tar.gz", hash = "sha256:363787653b71cd5dc4e2de30aaab835afd48b64e2257fe1b4b78efac01635e8c"}, - {file = "cfn_lint-0.78.2-py3-none-any.whl", hash = "sha256:5db9306faf9368ccbbd1ca1272b2b311cecc48499fa98303510d5c4bce478109"}, + {file = "cfn-lint-0.79.3.tar.gz", hash = "sha256:4197507bcb0f03d14acc4e7fa5487b7e2ccaba276a167cda0e364c4758c5ddaa"}, + {file = "cfn_lint-0.79.3-py3-none-any.whl", hash = "sha256:75a3ac3b906a410db33ccbaee5403e02faed424bab394160ab0ad00a7602a534"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "fb6f2d9e404a3e567ab1093426addd4fd33aee51d2a692bc4f3d1399fb8f5ff3" +content-hash = "7401594ead9f5c81df2b2eebb0c77e593ed73eae975e305ed59168d6ea4fa3c5" diff --git a/pyproject.toml b/pyproject.toml index 5b085f6bb91..cd27ac38cc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ all = ["pydantic", "aws-xray-sdk", "fastjsonschema"] aws-sdk = ["boto3"] [tool.poetry.group.dev.dependencies] -cfn-lint = "0.78.2" +cfn-lint = "0.79.3" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" From 453a8f2d510bfd899cc09d5d8fc0098b4b8f7c76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 26 Jul 2023 23:31:31 +0100 Subject: [PATCH 11/92] chore(ci): changelog rebuild (#2849) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 293e92155c2..9fb23be3099 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,40 @@ # Unreleased +## Maintenance + +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) + ## [v2.22.0] - 2023-07-25 +## Bug Fixes + +* **parameters:** distinct cache key for single vs path with same name ([#2839](https://github.com/aws-powertools/powertools-lambda-python/issues/2839)) + +## Documentation + +* **community:** new batch processing article ([#2828](https://github.com/aws-powertools/powertools-lambda-python/issues/2828)) +* **parameters:** improve readability on error handling get_parameter… ([#2833](https://github.com/aws-powertools/powertools-lambda-python/issues/2833)) + +## Features + +* **general:** add support for Python 3.11 ([#2820](https://github.com/aws-powertools/powertools-lambda-python/issues/2820)) + ## Maintenance * version bump +* **ci:** add baking time for layer build ([#2834](https://github.com/aws-powertools/powertools-lambda-python/issues/2834)) +* **ci:** build changelog on a schedule only ([#2832](https://github.com/aws-powertools/powertools-lambda-python/issues/2832)) +* **deps:** bump actions/setup-python from 4.6.1 to 4.7.0 ([#2821](https://github.com/aws-powertools/powertools-lambda-python/issues/2821)) +* **deps-dev:** bump ruff from 0.0.278 to 0.0.279 ([#2822](https://github.com/aws-powertools/powertools-lambda-python/issues/2822)) +* **deps-dev:** bump cfn-lint from 0.78.1 to 0.78.2 ([#2823](https://github.com/aws-powertools/powertools-lambda-python/issues/2823)) +* **deps-dev:** bump ruff from 0.0.279 to 0.0.280 ([#2836](https://github.com/aws-powertools/powertools-lambda-python/issues/2836)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.0 to 1.28.10 ([#2837](https://github.com/aws-powertools/powertools-lambda-python/issues/2837)) From b6463a95acc5e4d1e796cd7b5dc4cbbb63ba07bc Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Thu, 27 Jul 2023 18:10:48 +0200 Subject: [PATCH 12/92] docs(batch): new visuals and error handling section (#2857) * fix(parameters): make cache aware of single vs multiple calls Signed-off-by: heitorlessa * chore: cleanup, add test for single and nested Signed-off-by: heitorlessa * docs(batch): simplify background with diagram and wording Signed-off-by: heitorlessa * docs: recommend sqs new record.json_body Signed-off-by: heitorlessa * docs: add code annotation for more details Signed-off-by: heitorlessa * docs: add initial error handling section Signed-off-by: heitorlessa * docs: add visual for partial failure mechanics Signed-off-by: heitorlessa * docs: add fifo and stream sequence numbers Signed-off-by: heitorlessa * docs: revamp ctx manager processing Signed-off-by: heitorlessa * docs: highlight use of model in BatchProcessor Signed-off-by: heitorlessa * docs: diagram for BYOP --------- Signed-off-by: heitorlessa --- .gitleaksignore | 3 + docs/utilities/batch.md | 274 ++++++++++++++++-- .../src/context_manager_access.py | 5 +- .../src/context_manager_access_output.txt | 12 + ...context_manager_access_output_pydantic.txt | 17 ++ .../src/getting_started_dynamodb.py | 2 +- .../src/getting_started_error_handling.py | 35 +++ .../src/getting_started_kinesis.py | 2 +- .../src/getting_started_sqs.py | 19 +- .../src/getting_started_sqs_fifo.py | 10 +- 10 files changed, 333 insertions(+), 46 deletions(-) create mode 100644 .gitleaksignore create mode 100644 examples/batch_processing/src/context_manager_access_output.txt create mode 100644 examples/batch_processing/src/context_manager_access_output_pydantic.txt create mode 100644 examples/batch_processing/src/getting_started_error_handling.py diff --git a/.gitleaksignore b/.gitleaksignore new file mode 100644 index 00000000000..d501e5cc212 --- /dev/null +++ b/.gitleaksignore @@ -0,0 +1,3 @@ +examples/batch_processing/src/context_manager_access_output_pydantic.txt:aws-access-token:10 +examples/batch_processing/src/context_manager_access_output_pydantic.txt:aws-access-token:15 +examples/batch_processing/src/context_manager_access_output.txt:aws-access-token:10 diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 488be06e60b..57e0a6020b1 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -5,6 +5,30 @@ description: Utility The batch processing utility handles partial failures when processing batches from Amazon SQS, Amazon Kinesis Data Streams, and Amazon DynamoDB Streams. +```mermaid +stateDiagram-v2 + direction LR + BatchSource: Amazon SQS

Amazon Kinesis Data Streams

Amazon DynamoDB Streams

+ LambdaInit: Lambda invocation + BatchProcessor: Batch Processor + RecordHandler: Record Handler function + YourLogic: Your logic to process each batch item + LambdaResponse: Lambda response + + BatchSource --> LambdaInit + + LambdaInit --> BatchProcessor + BatchProcessor --> RecordHandler + + state BatchProcessor { + [*] --> RecordHandler: Your function + RecordHandler --> YourLogic + } + + RecordHandler --> BatchProcessor: Collect results + BatchProcessor --> LambdaResponse: Report items that failed processing +``` + ## Key features * Reports batch item failures to reduce number of retries for a record upon errors @@ -16,12 +40,21 @@ The batch processing utility handles partial failures when processing batches fr When using SQS, Kinesis Data Streams, or DynamoDB Streams as a Lambda event source, your Lambda functions are triggered with a batch of messages. -If your function fails to process any message from the batch, the entire batch returns to your queue or stream. This same batch is then retried until either condition happens first: **a)** your Lambda function returns a successful response, **b)** record reaches maximum retry attempts, or **c)** when records expire. +If your function fails to process any message from the batch, the entire batch returns to your queue or stream. This same batch is then retried until either condition happens first: **a)** your Lambda function returns a successful response, **b)** record reaches maximum retry attempts, or **c)** records expire. + +```mermaid +journey + section Conditions + Successful response: 5: Success + Maximum retries: 3: Failure + Records expired: 1: Failure +``` -With this utility, batch records are processed individually – only messages that failed to be processed return to the queue or stream for a further retry. This works when two mechanisms are in place: +This behavior changes when you enable Report Batch Item Failures feature in your Lambda function event source configuration: -1. `ReportBatchItemFailures` is set in your SQS, Kinesis, or DynamoDB event source properties -2. [A specific response](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank" rel="nofollow"} is returned so Lambda knows which records should not be deleted during partial responses + +* [**SQS queues**](#sqs-standard). Only messages reported as failure will return to the queue for a retry, while successful ones will be deleted. +* [**Kinesis data streams**](#kinesis-and-dynamodb-streams) and [**DynamoDB streams**](#kinesis-and-dynamodb-streams). Single reported failure will use its sequence number as the stream checkpoint. Multiple reported failures will use the lowest sequence number as checkpoint. @@ -32,14 +65,16 @@ With this utility, batch records are processed individually – only messages th ## Getting started -Regardless whether you're using SQS, Kinesis Data Streams or DynamoDB Streams, you must configure your Lambda function event source to use `ReportBatchItemFailures`. +For this feature to work, you need to **(1)** configure your Lambda function event source to use `ReportBatchItemFailures`, and **(2)** return [a specific response](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank" rel="nofollow"} to report which records failed to be processed. -You do not need any additional IAM permissions to use this utility, except for what each event source requires. +You use your preferred deployment framework to set the correct configuration while this utility handles the correct response to be returned. ### Required resources The remaining sections of the documentation will rely on these samples. For completeness, this demonstrates IAM permissions and Dead Letter Queue where batch records will be sent after 2 retries were attempted. +!!! note "You do not need any additional IAM permissions to use this utility, except for what each event source requires." + === "SQS" ```yaml title="template.yaml" hl_lines="30-31" @@ -66,15 +101,18 @@ Processing batches from SQS works in three stages: 2. Define your function to handle each batch record, and use [`SQSRecord`](data_classes.md#sqs){target="_blank" rel="nofollow"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing -???+ info - This code example optionally uses Tracer and Logger for completion. +!!! info "This code example uses Tracer and Logger for completion." === "Recommended" - ```python hl_lines="4-9 12 18 28" + ```python hl_lines="2-7 10 16 24" --8<-- "examples/batch_processing/src/getting_started_sqs.py" ``` + 1. **Step 1**. Creates a partial failure batch processor for SQS queues. See [partial failure mechanics for details](#partial-failure-mechanics) + 2. **Step 2**. Defines a function to receive one record at a time from the batch + 3. **Step 3**. Kicks off processing + === "As a context manager" ```python hl_lines="4-5 8 14 25-26 29" @@ -108,10 +146,12 @@ This helps preserve the ordering of messages in your queue. === "Recommended" - ```python hl_lines="5-6 11 27" + ```python hl_lines="2-6 9 23" --8<-- "examples/batch_processing/src/getting_started_sqs_fifo.py" ``` + 1. **Step 1**. Creates a partial failure batch processor for SQS FIFO queues. See [partial failure mechanics for details](#partial-failure-mechanics) + === "As a context manager" ```python hl_lines="4 8" @@ -132,8 +172,7 @@ Processing batches from Kinesis works in three stages: 2. Define your function to handle each batch record, and use [`KinesisStreamRecord`](data_classes.md#kinesis-streams){target="_blank" rel="nofollow"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing -???+ info - This code example optionally uses Tracer and Logger for completion. +!!! info "This code example uses Tracer and Logger for completion." === "Recommended" @@ -141,6 +180,8 @@ Processing batches from Kinesis works in three stages: --8<-- "examples/batch_processing/src/getting_started_kinesis.py" ``` + 1. **Step 1**. Creates a partial failure batch processor for Kinesis Data Streams. See [partial failure mechanics for details](#partial-failure-mechanics) + === "As a context manager" ```python hl_lines="3-5 8 14 23-25 28" @@ -175,8 +216,7 @@ Processing batches from DynamoDB Streams works in three stages: 2. Define your function to handle each batch record, and use [`DynamoDBRecord`](data_classes.md#dynamodb-streams){target="_blank" rel="nofollow"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing -???+ info - This code example optionally uses Tracer and Logger for completion. +!!! info "This code example uses Tracer and Logger for completion." === "Recommended" @@ -184,6 +224,8 @@ Processing batches from DynamoDB Streams works in three stages: --8<-- "examples/batch_processing/src/getting_started_dynamodb.py" ``` + 1. **Step 1**. Creates a partial failure batch processor for DynamoDB Streams. See [partial failure mechanics for details](#partial-failure-mechanics) + === "As a context manager" ```python hl_lines="5-7 10 16 28-30 33" @@ -210,24 +252,157 @@ Processing batches from DynamoDB Streams works in three stages: --8<-- "examples/batch_processing/src/getting_started_dynamodb_event.json" ``` +### Error handling + +By default, we catch any exception raised by your record handler function. This allows us to **(1)** continue processing the batch, **(2)** collect each batch item that failed processing, and **(3)** return the appropriate response correctly without failing your Lambda function execution. + +=== "Sample error handling with custom exception" + + ```python title="" hl_lines="24" + --8<-- "examples/batch_processing/src/getting_started_error_handling.py" + ``` + + 1. Any exception works here. See [extending BatchProcessor section, if you want to override this behavior.](#extending-batchprocessor) + + 2. Exceptions raised in `record_handler` will propagate to `process_partial_response`.

We catch them and include each failed batch item identifier in the response dictionary (see `Sample response` tab). + +=== "Sample response" + + ```json + --8<-- "examples/batch_processing/src/getting_started_sqs_response.json" + ``` + ### Partial failure mechanics -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: +All batch items will be passed to the record handler for processing, even if exceptions are thrown - Here's the behavior after completing the batch: * **All records successfully processed**. We will return an empty list of item failures `{'batchItemFailures': []}` * **Partial success with some exceptions**. We will return a list of all item IDs/sequence numbers that failed processing * **All records failed to be processed**. We will raise `BatchProcessingError` exception with a list of all exceptions raised when processing +The following sequence diagrams explain how each Batch processor behaves under different scenarios. + +#### SQS Standard + +> Read more about [Batch Failure Reporting feature in AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank"}. + +Sequence diagram to explain how [`BatchProcessor` works](#processing-messages-from-sqs) with SQS Standard queues. + +
+```mermaid +sequenceDiagram + autonumber + participant SQS queue + participant Lambda service + participant Lambda function + Lambda service->>SQS queue: Poll + Lambda service->>Lambda function: Invoke (batch event) + Lambda function->>Lambda service: Report some failed messages + activate SQS queue + Lambda service->>SQS queue: Delete successful messages + SQS queue-->>SQS queue: Failed messages return + Note over SQS queue,Lambda service: Process repeat + deactivate SQS queue +``` +SQS mechanism with Batch Item Failures +
+ +#### SQS FIFO + +> Read more about [Batch Failure Reporting feature in AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank"}. + +Sequence diagram to explain how [`SqsFifoPartialProcessor` works](#fifo-queues) with SQS FIFO queues. + +
+```mermaid +sequenceDiagram + autonumber + participant SQS queue + participant Lambda service + participant Lambda function + Lambda service->>SQS queue: Poll + Lambda service->>Lambda function: Invoke (batch event) + activate Lambda function + Lambda function-->Lambda function: Process 2 out of 10 batch items + Lambda function--xLambda function: Fail on 3rd batch item + Lambda function->>Lambda service: Report 3rd batch item and unprocessed messages as failure + deactivate Lambda function + activate SQS queue + Lambda service->>SQS queue: Delete successful messages (1-2) + SQS queue-->>SQS queue: Failed messages return (3-10) + deactivate SQS queue +``` +SQS FIFO mechanism with Batch Item Failures +
+ +#### Kinesis and DynamoDB Streams + +> Read more about [Batch Failure Reporting feature](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-batchfailurereporting){target="_blank"}. + +Sequence diagram to explain how `BatchProcessor` works with both [Kinesis Data Streams](#processing-messages-from-kinesis) and [DynamoDB Streams](#processing-messages-from-dynamodb). + +For brevity, we will use `Streams` to refer to either services. For theory on stream checkpoints, see this [blog post](https://aws.amazon.com/blogs/compute/optimizing-batch-processing-with-custom-checkpoints-in-aws-lambda/){target="_blank"} + +
+```mermaid +sequenceDiagram + autonumber + participant Streams + participant Lambda service + participant Lambda function + Lambda service->>Streams: Poll latest records + Lambda service->>Lambda function: Invoke (batch event) + activate Lambda function + Lambda function-->Lambda function: Process 2 out of 10 batch items + Lambda function--xLambda function: Fail on 3rd batch item + Lambda function-->Lambda function: Continue processing batch items (4-10) + Lambda function->>Lambda service: Report batch item as failure (3) + deactivate Lambda function + activate Streams + Lambda service->>Streams: Checkpoints to sequence number from 3rd batch item + Lambda service->>Streams: Poll records starting from updated checkpoint + deactivate Streams +``` +Kinesis and DynamoDB streams mechanism with single batch item failure +
+ +The behavior changes slightly when there are multiple item failures. Stream checkpoint is updated to the lowest sequence number reported. + +!!! important "Note that the batch item sequence number could be different from batch item number in the illustration." + +
+```mermaid +sequenceDiagram + autonumber + participant Streams + participant Lambda service + participant Lambda function + Lambda service->>Streams: Poll latest records + Lambda service->>Lambda function: Invoke (batch event) + activate Lambda function + Lambda function-->Lambda function: Process 2 out of 10 batch items + Lambda function--xLambda function: Fail on 3-5 batch items + Lambda function-->Lambda function: Continue processing batch items (6-10) + Lambda function->>Lambda service: Report batch items as failure (3-5) + deactivate Lambda function + activate Streams + Lambda service->>Streams: Checkpoints to lowest sequence number + Lambda service->>Streams: Poll records starting from updated checkpoint + deactivate Streams +``` +Kinesis and DynamoDB streams mechanism with multiple batch item failures +
+ ### Processing messages asynchronously -!!! tip "New to AsyncIO? Read this [comprehensive guide first](https://realpython.com/async-io-python/){target="_blank" rel="nofollow"}." +> New to AsyncIO? Read this [comprehensive guide first](https://realpython.com/async-io-python/){target="_blank" rel="nofollow"}. You can use `AsyncBatchProcessor` class and `async_process_partial_response` function to process messages concurrently. ???+ question "When is this useful?" Your use case might be able to process multiple records at the same time without conflicting with one another. - For example, imagine you need to process multiple loyalty points and incrementally save in a database. While you await the database to confirm your records are saved, you could start processing another request concurrently. + For example, imagine you need to process multiple loyalty points and incrementally save them in the database. While you await the database to confirm your records are saved, you could start processing another request concurrently. The reason this is not the default behaviour is that not all use cases can handle concurrency safely (e.g., loyalty points must be updated in order). @@ -236,9 +411,7 @@ You can use `AsyncBatchProcessor` class and `async_process_partial_response` fun ``` ???+ warning "Using tracer?" - `AsyncBatchProcessor` uses `asyncio.gather` which can cause side effects and reach trace limits at high concurrency. - - See [Tracing concurrent asynchronous functions](../core/tracer.md#concurrent-asynchronous-functions){target="_blank" rel="nofollow"}. + `AsyncBatchProcessor` uses `asyncio.gather`. This might cause [side effects and reach trace limits at high concurrency](../core/tracer.md#concurrent-asynchronous-functions){target="_blank"}. ## Advanced @@ -250,7 +423,7 @@ Inheritance is importance because we need to access message IDs and sequence num === "SQS" - ```python hl_lines="8 17 27 35" + ```python hl_lines="8 17 21 27 35" --8<-- "examples/batch_processing/src/pydantic_sqs.py" ``` @@ -288,12 +461,36 @@ Inheritance is importance because we need to access message IDs and sequence num Use the context manager to access a list of all returned values from your `record_handler` function. -* **When successful**. We will include a tuple with `success`, the result of `record_handler`, and the batch record -* **When failed**. We will include a tuple with `fail`, exception as a string, and the batch record +* **When successful**. We include a tuple with **1/** `success`, **2/** the result of `record_handler`, and **3/** the batch item +* **When failed**. We include a tuple with **1/** `fail`, **2/** exception as a string, and **3/** the batch item serialized as Event Source Data Class or Pydantic model. -```python hl_lines="28-33" title="Accessing processed messages via context manager" ---8<-- "examples/batch_processing/src/context_manager_access.py" -``` +!!! note "If a Pydantic model fails validation early, we serialize its failure record as Event Source Data Class to be able to collect message ID/sequence numbers etc." + +=== "Accessing raw processed messages" + + ```python hl_lines="29-36" + --8<-- "examples/batch_processing/src/context_manager_access.py" + ``` + + 1. Context manager requires the records list. This is typically handled by `process_partial_response`. + 2. Cause contains `exception` str if failed, or `success` otherwise. + +=== "Sample processed messages" + + ```python + --8<-- "examples/batch_processing/src/context_manager_access_output.txt" + ``` + + 1. Sample exception could have raised from within `record_handler` function. + +=== "Sample processed messages (Pydantic)" + + ```python + --8<-- "examples/batch_processing/src/context_manager_access_output_pydantic.txt" + ``` + + 1. Sample when a model fails validation early.

Batch item (3rd item) is serialized to the respective Event Source Data Class event type. + 2. Sample when model validated successfully but another exception was raised during processing. ### Accessing Lambda Context @@ -339,6 +536,31 @@ For these scenarios, you can subclass `BatchProcessor` and quickly override `suc You can create your own partial batch processor from scratch by inheriting the `BasePartialProcessor` class, and implementing `_prepare()`, `_clean()`, `_process_record()` and `_async_process_record()`. + +
+```mermaid +classDiagram + direction LR + class BasePartialProcessor { + <> + +_prepare() + +_clean() + +_process_record_(record: Dict) + +_async_process_record_() + } + + class YourCustomProcessor { + +_prepare() + +_clean() + +_process_record_(record: Dict) + +_async_process_record_() + } + + BasePartialProcessor <|-- YourCustomProcessor : implement +``` +Visual representation to bring your own processor +
+ * **`_process_record()`** – handles all processing logic for each individual message of a batch, including calling the `record_handler` (self.handler) * **`_prepare()`** – called once as part of the processor initialization * **`_clean()`** – teardown logic called once after `_process_record` completes diff --git a/examples/batch_processing/src/context_manager_access.py b/examples/batch_processing/src/context_manager_access.py index 9882092bd83..05cf612a6ae 100644 --- a/examples/batch_processing/src/context_manager_access.py +++ b/examples/batch_processing/src/context_manager_access.py @@ -26,14 +26,15 @@ def record_handler(record: SQSRecord): @logger.inject_lambda_context @tracer.capture_lambda_handler def lambda_handler(event, context: LambdaContext): - batch = event["Records"] + batch = event["Records"] # (1)! with processor(records=batch, handler=record_handler): processed_messages: List[Tuple] = processor.process() for message in processed_messages: status: Literal["success"] | Literal["fail"] = message[0] + cause: str = message[1] # (2)! record: SQSRecord = message[2] - logger.info(status, record=record) + logger.info(status, record=record, cause=cause) return processor.response() diff --git a/examples/batch_processing/src/context_manager_access_output.txt b/examples/batch_processing/src/context_manager_access_output.txt new file mode 100644 index 00000000000..cf3d6267f4d --- /dev/null +++ b/examples/batch_processing/src/context_manager_access_output.txt @@ -0,0 +1,12 @@ +[ + ( + "fail", + " + ), + ( + "success", + "success", + {'messageId': '88891c36-32eb-4a25-9905-654a32916893', 'receiptHandle': 'AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a', 'body': 'success', '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-1'} + ) +] diff --git a/examples/batch_processing/src/context_manager_access_output_pydantic.txt b/examples/batch_processing/src/context_manager_access_output_pydantic.txt new file mode 100644 index 00000000000..748a6e61aa0 --- /dev/null +++ b/examples/batch_processing/src/context_manager_access_output_pydantic.txt @@ -0,0 +1,17 @@ +[ + ( + "fail", # (1)! + ":1 validation error for OrderSqs\nbody\n JSON object must be str, bytes or bytearray (type=type_error.json)", + + ), + ( + "success", + "success", + {'messageId': '88891c36-32eb-4a25-9905-654a32916893', 'receiptHandle': 'AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a', 'body': 'success', '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-1'} + ), + ( + "fail", # (2)! + ":Failed to process record.", + OrderSqs(messageId='9d0bfba5-d213-4b64-89bd-f4fbd7e58358', receiptHandle='AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a', body=Order(item={'type': 'fail'}), attributes=SqsAttributesModel(ApproximateReceiveCount='1', ApproximateFirstReceiveTimestamp=datetime.datetime(2018, 12, 17, 21, 37, 29, 185000, tzinfo=datetime.timezone.utc), MessageDeduplicationId=None, MessageGroupId=None, SenderId='AIDAIENQZJOLO23YVJ4VO', SentTimestamp=datetime.datetime(2018, 12, 17, 21, 37, 29, 183000, tzinfo=datetime.timezone.utc), SequenceNumber=None, AWSTraceHeader=None), messageAttributes={}, md5OfBody='e4e68fb7bd0e697a0ae8f1bb342846b3', md5OfMessageAttributes=None, eventSource='aws:sqs', eventSourceARN='arn:aws:sqs:us-east-2:123456789012:my-queue', awsRegion='us-east-1') + ) +] diff --git a/examples/batch_processing/src/getting_started_dynamodb.py b/examples/batch_processing/src/getting_started_dynamodb.py index 61990e2bd26..f56f0324bad 100644 --- a/examples/batch_processing/src/getting_started_dynamodb.py +++ b/examples/batch_processing/src/getting_started_dynamodb.py @@ -11,7 +11,7 @@ ) from aws_lambda_powertools.utilities.typing import LambdaContext -processor = BatchProcessor(event_type=EventType.DynamoDBStreams) +processor = BatchProcessor(event_type=EventType.DynamoDBStreams) # (1)! tracer = Tracer() logger = Logger() diff --git a/examples/batch_processing/src/getting_started_error_handling.py b/examples/batch_processing/src/getting_started_error_handling.py new file mode 100644 index 00000000000..7307f0d0d09 --- /dev/null +++ b/examples/batch_processing/src/getting_started_error_handling.py @@ -0,0 +1,35 @@ +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.utilities.batch import ( + BatchProcessor, + EventType, + process_partial_response, +) +from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord +from aws_lambda_powertools.utilities.typing import LambdaContext + +processor = BatchProcessor(event_type=EventType.SQS) +tracer = Tracer() +logger = Logger() + + +class InvalidPayload(Exception): + ... + + +@tracer.capture_method +def record_handler(record: SQSRecord): + payload: str = record.body + logger.info(payload) + if not payload: + raise InvalidPayload("Payload does not contain minimum information to be processed.") # (1)! + + +@logger.inject_lambda_context +@tracer.capture_lambda_handler +def lambda_handler(event, context: LambdaContext): + return process_partial_response( # (2)! + event=event, + record_handler=record_handler, + processor=processor, + context=context, + ) diff --git a/examples/batch_processing/src/getting_started_kinesis.py b/examples/batch_processing/src/getting_started_kinesis.py index 179154e3b1f..a3410fa57a2 100644 --- a/examples/batch_processing/src/getting_started_kinesis.py +++ b/examples/batch_processing/src/getting_started_kinesis.py @@ -9,7 +9,7 @@ ) from aws_lambda_powertools.utilities.typing import LambdaContext -processor = BatchProcessor(event_type=EventType.KinesisDataStreams) +processor = BatchProcessor(event_type=EventType.KinesisDataStreams) # (1)! tracer = Tracer() logger = Logger() diff --git a/examples/batch_processing/src/getting_started_sqs.py b/examples/batch_processing/src/getting_started_sqs.py index 8b6fe4c4266..c8c2facb09a 100644 --- a/examples/batch_processing/src/getting_started_sqs.py +++ b/examples/batch_processing/src/getting_started_sqs.py @@ -1,5 +1,3 @@ -import json - from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.utilities.batch import ( BatchProcessor, @@ -9,20 +7,23 @@ from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord from aws_lambda_powertools.utilities.typing import LambdaContext -processor = BatchProcessor(event_type=EventType.SQS) +processor = BatchProcessor(event_type=EventType.SQS) # (1)! tracer = Tracer() logger = Logger() @tracer.capture_method -def record_handler(record: SQSRecord): - payload: str = record.body - if payload: - item: dict = json.loads(payload) - logger.info(item) +def record_handler(record: SQSRecord): # (2)! + payload: str = record.json_body # if json string data, otherwise record.body for str + logger.info(payload) @logger.inject_lambda_context @tracer.capture_lambda_handler def lambda_handler(event, context: LambdaContext): - return process_partial_response(event=event, record_handler=record_handler, processor=processor, context=context) + return process_partial_response( # (3)! + event=event, + record_handler=record_handler, + processor=processor, + context=context, + ) diff --git a/examples/batch_processing/src/getting_started_sqs_fifo.py b/examples/batch_processing/src/getting_started_sqs_fifo.py index d30fb319c85..95d7463eb18 100644 --- a/examples/batch_processing/src/getting_started_sqs_fifo.py +++ b/examples/batch_processing/src/getting_started_sqs_fifo.py @@ -1,5 +1,3 @@ -import json - from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.utilities.batch import ( SqsFifoPartialProcessor, @@ -8,17 +6,15 @@ from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord from aws_lambda_powertools.utilities.typing import LambdaContext -processor = SqsFifoPartialProcessor() +processor = SqsFifoPartialProcessor() # (1)! tracer = Tracer() logger = Logger() @tracer.capture_method def record_handler(record: SQSRecord): - payload: str = record.body - if payload: - item: dict = json.loads(payload) - logger.info(item) + payload: str = record.json_body # if json string data, otherwise record.body for str + logger.info(payload) @logger.inject_lambda_context From 5c0aeda4160e2559749cbf2aea38d2f2aa9caf23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:38:21 +0200 Subject: [PATCH 13/92] chore(deps): bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs (#2859) 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 4d24b69c3f0..eaa3942f01e 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,5 +1,5 @@ # v9.1.18 -FROM squidfunk/mkdocs-material@sha256:33e28bdae302bc1aa9c6783dd863742416cb1174bae4ad9d7bcc5b2efe685639 +FROM squidfunk/mkdocs-material@sha256:cd3a522b3282071586552499611f71206db0aec145d4d53822bc6fde76792cf8 # pip-compile --generate-hashes --output-file=requirements.txt requirements.in COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From d311a4706ab39bf439dbe37f3a0e7f4945d2f914 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 27 Jul 2023 21:41:12 +0100 Subject: [PATCH 14/92] docs(tutorial): add support for Python 3.11 (#2860) --- docs/tutorial/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index b0aca95dd12..28021ea191a 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -20,11 +20,11 @@ Let's clone our sample project before we add one feature at a time. Bootstrap directly via SAM CLI: ```shell - sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.10 --no-tracing + sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.11 --no-tracing ``` ```bash title="Use SAM CLI to initialize the sample project" -sam init --runtime python3.10 --dependency-manager pip --app-template hello-world --name powertools-quickstart +sam init --runtime python3.11 --dependency-manager pip --app-template hello-world --name powertools-quickstart ``` ### Project structure From 173b25e656733853b0c32923b81d9f793140a5e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:56:54 +0100 Subject: [PATCH 15/92] chore(deps-dev): bump mypy-boto3-ssm from 1.28.0 to 1.28.12 (#2863) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index b5e901ac2b2..97609aabaf5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1554,13 +1554,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-ssm" -version = "1.28.0" -description = "Type annotations for boto3.SSM 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.12" +description = "Type annotations for boto3.SSM 1.28.12 service generated with mypy-boto3-builder 7.15.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-ssm-1.28.0.tar.gz", hash = "sha256:15482d2bff7995230549d145547f0ea92d01b68716aa25297e2a2da015922309"}, - {file = "mypy_boto3_ssm-1.28.0-py3-none-any.whl", hash = "sha256:e6ac60818c807baeeb0ef6714832c23904f2ed463fc40133059e2f63abd432fa"}, + {file = "mypy-boto3-ssm-1.28.12.tar.gz", hash = "sha256:78b4cef65e18ae6714022d95955a51208a1614ca2dc6757735c9527c96cd7c14"}, + {file = "mypy_boto3_ssm-1.28.12-py3-none-any.whl", hash = "sha256:5576d651129cdef275f2dcf7d20dd6df17e45d1534e5020e7a1aac32227215d8"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "7401594ead9f5c81df2b2eebb0c77e593ed73eae975e305ed59168d6ea4fa3c5" +content-hash = "997f30d5f8210a41774d0bceb21aaf75c6eaebe2e52b14d228ec53ec28112015" diff --git a/pyproject.toml b/pyproject.toml index cd27ac38cc3..cb5af80389b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,7 @@ mypy-boto3-dynamodb = "^1.28.11" mypy-boto3-lambda = "^1.28.11" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.28.3" -mypy-boto3-ssm = "^1.28.0" +mypy-boto3-ssm = "^1.28.12" mypy-boto3-s3 = "^1.28.8" mypy-boto3-xray = "^1.28.0" types-requests = "^2.31.0" From a88e7895354f8e291402cf4c15739de357cc293f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 23:27:50 +0100 Subject: [PATCH 16/92] chore(deps-dev): bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 (#2861) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 97609aabaf5..33990182c03 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1428,13 +1428,13 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-appconfig" -version = "1.28.0" -description = "Type annotations for boto3.AppConfig 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.12" +description = "Type annotations for boto3.AppConfig 1.28.12 service generated with mypy-boto3-builder 7.15.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfig-1.28.0.tar.gz", hash = "sha256:753044339ce1da00e0b60f387ed957013712ab69ca51a9b56859a4ae502c806a"}, - {file = "mypy_boto3_appconfig-1.28.0-py3-none-any.whl", hash = "sha256:5708545675610ceb686339e90f4d6f8276f9e2ad2f15db2833ebc593185708f5"}, + {file = "mypy-boto3-appconfig-1.28.12.tar.gz", hash = "sha256:02080219c25b7d7837257d070109ba1fe55cd281eb1f8115ca94556d25453e29"}, + {file = "mypy_boto3_appconfig-1.28.12-py3-none-any.whl", hash = "sha256:4796bdae21a86de03198c181e514875287b2cbac46a7718d25128cb61c457f0a"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "997f30d5f8210a41774d0bceb21aaf75c6eaebe2e52b14d228ec53ec28112015" +content-hash = "081c3a75c0b8cdd812fea4cdc0970a4eed60f05ba69b38fa39f0b6eee6c0833c" diff --git a/pyproject.toml b/pyproject.toml index cb5af80389b..ed7363da63d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ aws-cdk-lib = "^2.88.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" -mypy-boto3-appconfig = "^1.28.0" +mypy-boto3-appconfig = "^1.28.12" mypy-boto3-cloudformation = "^1.28.10" mypy-boto3-cloudwatch = "^1.28.0" mypy-boto3-dynamodb = "^1.28.11" From 450ed9d7878db7534773b6e1035587db01ec1f48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 23:54:53 +0100 Subject: [PATCH 17/92] chore(deps-dev): bump cfn-lint from 0.79.3 to 0.79.4 (#2862) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 33990182c03..8a86cf549e7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -365,13 +365,13 @@ files = [ [[package]] name = "cfn-lint" -version = "0.79.3" +version = "0.79.4" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "cfn-lint-0.79.3.tar.gz", hash = "sha256:4197507bcb0f03d14acc4e7fa5487b7e2ccaba276a167cda0e364c4758c5ddaa"}, - {file = "cfn_lint-0.79.3-py3-none-any.whl", hash = "sha256:75a3ac3b906a410db33ccbaee5403e02faed424bab394160ab0ad00a7602a534"}, + {file = "cfn-lint-0.79.4.tar.gz", hash = "sha256:d4ddb83907b4d385ac958763486040591302f9aeb33d49b14399f580fddef1ae"}, + {file = "cfn_lint-0.79.4-py3-none-any.whl", hash = "sha256:86ca9873fefb40ccf321d0dc9b9c2fe1f6cc3aadb373bc10ae6fc5a54e37cf5b"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "081c3a75c0b8cdd812fea4cdc0970a4eed60f05ba69b38fa39f0b6eee6c0833c" +content-hash = "642cdcf6c87de47e909733dc3f0e5e77060d38a85b10eef8134f7e3366f8aabd" diff --git a/pyproject.toml b/pyproject.toml index ed7363da63d..ead84fa5f11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ all = ["pydantic", "aws-xray-sdk", "fastjsonschema"] aws-sdk = ["boto3"] [tool.poetry.group.dev.dependencies] -cfn-lint = "0.79.3" +cfn-lint = "0.79.4" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" From 2e821e0347823c4a5c397a5d526940b98cae811f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 00:22:00 +0100 Subject: [PATCH 18/92] chore(deps-dev): bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 (#2865) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8a86cf549e7..1c04cc3fdd5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1470,13 +1470,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudwatch" -version = "1.28.0" -description = "Type annotations for boto3.CloudWatch 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.12" +description = "Type annotations for boto3.CloudWatch 1.28.12 service generated with mypy-boto3-builder 7.15.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudwatch-1.28.0.tar.gz", hash = "sha256:c34cc45c8a57702e11cf38de590af447d90cd3ea68328ea2908452d8a09d471a"}, - {file = "mypy_boto3_cloudwatch-1.28.0-py3-none-any.whl", hash = "sha256:8812c6120111798f84b2e1fe5808aae1f5766c183746ea336dec14f9bdf3308b"}, + {file = "mypy-boto3-cloudwatch-1.28.12.tar.gz", hash = "sha256:c3205f75845a6b9aff313f2e74e1f5e4b7462772946da9c27cf0fa09194f83b9"}, + {file = "mypy_boto3_cloudwatch-1.28.12-py3-none-any.whl", hash = "sha256:d81da96bc035265a53a72ff813250ae19af12a404f24adb86fcc1376c42de441"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "642cdcf6c87de47e909733dc3f0e5e77060d38a85b10eef8134f7e3366f8aabd" +content-hash = "1ccf0fb2c77ef8d02db090b863ee2e16c27dda9cb0a18586b0556855a690be5b" diff --git a/pyproject.toml b/pyproject.toml index ead84fa5f11..82ca67e85aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,7 @@ aws-cdk-lib = "^2.88.0" pytest-benchmark = "^4.0.0" mypy-boto3-appconfig = "^1.28.12" mypy-boto3-cloudformation = "^1.28.10" -mypy-boto3-cloudwatch = "^1.28.0" +mypy-boto3-cloudwatch = "^1.28.12" mypy-boto3-dynamodb = "^1.28.11" mypy-boto3-lambda = "^1.28.11" mypy-boto3-logs = "^1.28.1" From 7661e5c424235a6b284f760b5e64120753743d20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 08:58:04 +0100 Subject: [PATCH 19/92] chore(deps-dev): bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 (#2864) Bumps [mypy-boto3-cloudformation](https://github.com/youtype/mypy_boto3_builder) from 1.28.10 to 1.28.12. - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: mypy-boto3-cloudformation 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> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1c04cc3fdd5..a47307abccc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1456,13 +1456,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudformation" -version = "1.28.10" -description = "Type annotations for boto3.CloudFormation 1.28.10 service generated with mypy-boto3-builder 7.15.1" +version = "1.28.12" +description = "Type annotations for boto3.CloudFormation 1.28.12 service generated with mypy-boto3-builder 7.15.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.28.10.tar.gz", hash = "sha256:81632665c3c9a648a665af390c555e5a8ad6bf0d4a48e4729aa1ead11b643aef"}, - {file = "mypy_boto3_cloudformation-1.28.10-py3-none-any.whl", hash = "sha256:c2623baf32c3c47976a4454d5812367ee27cee7f3ab0fbe98818ac9020db54c0"}, + {file = "mypy-boto3-cloudformation-1.28.12.tar.gz", hash = "sha256:2a276c52a4907d5f0b111a5fd0d880b20d188905cd8b672cde5ac46363a8b3fa"}, + {file = "mypy_boto3_cloudformation-1.28.12-py3-none-any.whl", hash = "sha256:7b16b8a3000f9dff13ead9edcebd34ee19e2130d213ecf05b371e02048f1a7a3"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "1ccf0fb2c77ef8d02db090b863ee2e16c27dda9cb0a18586b0556855a690be5b" +content-hash = "f75331de0d0c9dadeeaf9a0bec41adfe9e124631bb5351d28575aa66c7a0a239" diff --git a/pyproject.toml b/pyproject.toml index 82ca67e85aa..10e67e6e520 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ aws-cdk-lib = "^2.88.0" "aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" mypy-boto3-appconfig = "^1.28.12" -mypy-boto3-cloudformation = "^1.28.10" +mypy-boto3-cloudformation = "^1.28.12" mypy-boto3-cloudwatch = "^1.28.12" mypy-boto3-dynamodb = "^1.28.11" mypy-boto3-lambda = "^1.28.11" From 7091c21861d01295f1b3a9faef2e296fe3c8f9de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 08:58:28 +0100 Subject: [PATCH 20/92] chore(ci): changelog rebuild (#2866) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fb23be3099..7db41bc6c73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,29 @@ # Unreleased +## Bug Fixes + +* **logger:** strip xray_trace_id when explicitly disabled ([#2852](https://github.com/aws-powertools/powertools-lambda-python/issues/2852)) + +## Documentation + +* **batch:** new visuals and error handling section ([#2857](https://github.com/aws-powertools/powertools-lambda-python/issues/2857)) +* **navigation:** add nofollow attribute ([#2842](https://github.com/aws-powertools/powertools-lambda-python/issues/2842)) +* **tutorial:** add support for Python 3.11 ([#2860](https://github.com/aws-powertools/powertools-lambda-python/issues/2860)) + ## Maintenance -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) +* **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) +* **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) +* **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) From d97d1763f96359dd8547736f8e045c3681db9557 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Fri, 28 Jul 2023 15:34:51 +0100 Subject: [PATCH 21/92] docs(navigation): remove nofollow attribute for internal links (#2867) --- docs/automation.md | 50 +++++++-------- docs/core/event_handler/api_gateway.md | 30 ++++----- docs/core/event_handler/appsync.md | 18 +++--- docs/core/logger.md | 18 +++--- docs/core/metrics.md | 26 ++++---- docs/core/tracer.md | 16 ++--- docs/index.md | 80 ++++++++++++------------ docs/maintainers.md | 18 +++--- docs/roadmap.md | 18 +++--- docs/security.md | 2 +- docs/tutorial/index.md | 84 +++++++++++++------------- docs/upgrade.md | 20 +++--- docs/utilities/batch.md | 14 ++--- docs/utilities/data_classes.md | 42 ++++++------- docs/utilities/feature_flags.md | 14 ++--- docs/utilities/idempotency.md | 24 ++++---- docs/utilities/jmespath_functions.md | 6 +- docs/utilities/middleware_factory.md | 12 ++-- docs/utilities/parameters.md | 26 ++++---- docs/utilities/parser.md | 4 +- docs/utilities/streaming.md | 2 +- docs/utilities/typing.md | 4 +- docs/utilities/validation.md | 6 +- 23 files changed, 267 insertions(+), 267 deletions(-) diff --git a/docs/automation.md b/docs/automation.md index 06b11525f9d..467df2b9803 100644 --- a/docs/automation.md +++ b/docs/automation.md @@ -21,7 +21,7 @@ This is a snapshot of our automated checks at a glance. ### Pre-commit checks -> [**Pre-commit configuration**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml){target="_blank" rel="nofollow"}. +> [**Pre-commit configuration**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml){target="_blank"}. Pre-commit checks are crucial for a fast feedback loop while ensuring security practices at the individual change level. @@ -29,13 +29,13 @@ To prevent scenarios where these checks are intentionally omitted at the client !!! note "These run locally only for changed files" -* [**Merge conflict check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L10){target="_blank" rel="nofollow"}. Checks for merge strings in each individual change accidentally left unresolved to prevent breakage. -* [**Code linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L22){target="_blank" rel="nofollow"}. Linter checks for industry quality standards and known bad practices that could lead to abuse. -* [**CloudFormation linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L34){target="_blank" rel="nofollow"}. `cfn-lint` ensures [best practices](https://github.com/aws-cloudformation/cfn-lint/blob/86f0370bd43b400ed4c485180dbc2697f73367b2/docs/rules.md){target=""_blank"} at our documentation examples. -* [**Markdown linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L25){target="_blank}. Primarily [industry markdown practices](https://github.com/DavidAnson/markdownlint/blob/d01180ec5a014083ee9d574b693a8d7fbc1e566d/README.md#rules--aliases){target="_blank" rel="nofollow"} at this stage. +* [**Merge conflict check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L10){target="_blank" }. Checks for merge strings in each individual change accidentally left unresolved to prevent breakage. +* [**Code linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L22){target="_blank"}. Linter checks for industry quality standards and known bad practices that could lead to abuse. +* [**CloudFormation linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L34){target="_blank"}. `cfn-lint` ensures [best practices](https://github.com/aws-cloudformation/cfn-lint/blob/86f0370bd43b400ed4c485180dbc2697f73367b2/docs/rules.md){target=""_blank"} at our documentation examples. +* [**Markdown linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L25){target="_blank}. Primarily [industry markdown practices](https://github.com/DavidAnson/markdownlint/blob/d01180ec5a014083ee9d574b693a8d7fbc1e566d/README.md#rules--aliases){target="_blank"} at this stage. * [**GitHub Actions linting**](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank" rel="nofollow"}. `actionlint` ensures workflows follow [GitHub Actions security practices](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank" rel="nofollow"}. It guards against numerous [leading practices](https://github.com/rhysd/actionlint/blob/main/docs/checks.md){target="_blank" rel="nofollow"} to prevent common configuration mistakes, insecure inline scripts, among many others. -* [**Terraform linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L43){target="_blank" rel="nofollow"}. As of now, largely formatting until we increase our Terraform coverage in documentation examples. -* [**Secrets linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/.pre-commit-config.yaml#L49){target="_blank" rel="nofollow"}. Detects industry credentials that might be accidentally leaked in source code. +* [**Terraform linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.pre-commit-config.yaml#L43){target="_blank"}. As of now, largely formatting until we increase our Terraform coverage in documentation examples. +* [**Secrets linting**](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/.pre-commit-config.yaml#L49){target="_blank"}. Detects industry credentials that might be accidentally leaked in source code. ### Pre-Pull Request checks @@ -43,10 +43,10 @@ For an improved contributing experience, most of our checks can run locally. For !!! note "These are in addition to [pre-commit checks](#pre-commit-checks)." -* [**Static typing analysis**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L108). `mypy` checks for static typing annotations to prevent common bugs in Python that may or may not lead to abuse. -* [**Tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L31){target="_blank" rel="nofollow"}. We run `unit`, `functional`, and `performance` tests ([_see our definition_](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank" rel="nofollow"}). Besides breaking changes, we are investing in mutation testing to find additional sources of bugs and potential abuse. -* [**Security baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank" rel="nofollow"}. `bandit` detects common security issues defined by Python Code Quality Authority (PyCQA). -* [**Complexity baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L79){target="_blank" rel="nofollow"}. We run a series of maintenability and cyclomatic checks to reduce code and logic complexity. This aids reviewers' cognitive overhead and long-term maintainers revisiting legacy code at a later date. +* [**Static typing analysis**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L108){target="_blank"}. `mypy` checks for static typing annotations to prevent common bugs in Python that may or may not lead to abuse. +* [**Tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L31){target="_blank"}. We run `unit`, `functional`, and `performance` tests ([_see our definition_](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank"}). Besides breaking changes, we are investing in mutation testing to find additional sources of bugs and potential abuse. +* [**Security baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#testing-definition){target="_blank"}. `bandit` detects common security issues defined by Python Code Quality Authority (PyCQA). +* [**Complexity baseline**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/Makefile#L79){target="_blank"}. We run a series of maintainability and cyclomatic checks to reduce code and logic complexity. This aids reviewers' cognitive overhead and long-term maintainers revisiting legacy code at a later date. ### Pull Request checks @@ -54,13 +54,13 @@ While we trust contributors and maintainers do go through pre-commit and pre-pul !!! note "Checks described earlier are omitted to improve reading experience." -* [**Semantic PR title**](https://github.com/Ezard/semantic-prs){target="_blank" rel="nofollow"}. We enforce PR titles follow semantic naming, for example `chore(category): change`. This benefits contributors with a lower entry bar, no need for semantic commits. It also benefits everyone looking for an [useful changelog message](https://docs.powertools.aws.dev/lambda/python/latest/changelog/){target="_blank" rel="nofollow"} on **what** changed and **where**. -* [**Related issue check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L44){target="_blank" rel="nofollow"}. [Every change require an issue](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#contributing-via-pull-requests){target="_blank" rel="nofollow"} describing its needs. This enforces a PR has a related issue by blocking merge operations if missing. -* [**Acknowledgment check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L63){target="_blank" rel="nofollow"}. [Ensures PR template](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/PULL_REQUEST_TEMPLATE.md#L36){target="_blank" rel="nofollow"} is used and every contributor is aware of code redistribution. -* [**Code coverage diff**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/quality_check.yml#L73){target="_blank" rel="nofollow"}. Educates contributors and maintainers about code coverage differences for a given change. -* [**Contribution size check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_label_added.yml#L44){target="_blank" rel="nofollow"}. Suggests contributors and maintainers to break up large changes (100-499 LOC) in smaller PRs. It helps reduce overlooking security and other practices due to increased cognitive overhead. -* [**Dependency vulnerability check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/dependency-review.yml#L22){target="_blank" rel="nofollow"}. Verifies any dependency changes for common vulnerability exposures (CVEs), in addition to our daily check on any dependencies used (e.g., Python, Docker, Go, etc.) -* [**GitHub Actions security check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/secure_workflows.yml#L35){target="_blank" rel="nofollow"}. Enforces use of immutable 3rd-party GitHub Actions (_e.g., `actions/checkout@_`) to prevent abuse. Upgrades are handled by a [separate automated process](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/dependabot.yml#L4){target="_blank" rel="nofollow"} that includes a maintainer review to also prevent unexpected behavior changes. +* [**Semantic PR title**](https://github.com/Ezard/semantic-prs){target="_blank" rel="nofollow"}. We enforce PR titles follow semantic naming, for example `chore(category): change`. This benefits contributors with a lower entry bar, no need for semantic commits. It also benefits everyone looking for an [useful changelog message](https://docs.powertools.aws.dev/lambda/python/latest/changelog/){target="_blank"} on **what** changed and **where**. +* [**Related issue check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L44){target="_blank"}. [Every change require an issue](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/CONTRIBUTING.md#contributing-via-pull-requests){target="_blank"} describing its needs. This enforces a PR has a related issue by blocking merge operations if missing. +* [**Acknowledgment check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_opened_pr.yml#L63){target="_blank"}. [Ensures PR template](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/PULL_REQUEST_TEMPLATE.md#L36){target="_blank"} is used and every contributor is aware of code redistribution. +* [**Code coverage diff**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/quality_check.yml#L73){target="_blank"}. Educates contributors and maintainers about code coverage differences for a given change. +* [**Contribution size check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_label_added.yml#L44){target="_blank"}. Suggests contributors and maintainers to break up large changes (100-499 LOC) in smaller PRs. It helps reduce overlooking security and other practices due to increased cognitive overhead. +* [**Dependency vulnerability check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/dependency-review.yml#L22){target="_blank"}. Verifies any dependency changes for common vulnerability exposures (CVEs), in addition to our daily check on any dependencies used (e.g., Python, Docker, Go, etc.) +* [**GitHub Actions security check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/secure_workflows.yml#L35){target="_blank"}. Enforces use of immutable 3rd-party GitHub Actions (_e.g., `actions/checkout@_`) to prevent abuse. Upgrades are handled by a [separate automated process](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/dependabot.yml#L4){target="_blank"} that includes a maintainer review to also prevent unexpected behavior changes. ### After merge checks @@ -68,18 +68,18 @@ While we trust contributors and maintainers do go through pre-commit and pre-pul We strike a balance in security and contribution experience. These automated checks take several minutes to complete. Failures are reviewed by a maintainer on-call and before a release. -* [**End-to-end tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/run-e2e-tests.yml#L41){target="_blank" rel="nofollow"}. We run E2E with a [high degree of parallelization](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#test-runner-parallelization). While it is designed to also run locally, it may incur AWS charges to contributors. For additional security, all infrastructure is ephemeral per change and per Python version. -* [**SAST check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/codeql-analysis.yml#L20){target="_blank" rel="nofollow"}. GitHub CodeQL runs ~30m static analysis in the entire codebase. -* [**Security posture check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/ossf_scorecard.yml#L14){target="_blank" rel="nofollow"}. OSSF Scorecard runs numerous automated checks upon changes, and raises security alerts if [OSSF security practices](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank" rel="nofollow"} are no longer followed. -* [**Rebuild Changelog**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/build_changelog.yml#L23){target="_blank" rel="nofollow"}. We rebuild our entire changelog upon changes and create a PR for maintainers. This has the added benefit in keeping a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches){target="_blank" rel="nofollow"} while keeping removing error-prone tasks from maintainers. -* [**Stage documentation**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_push_docs.yml#L27C16-L27C16){target="_blank" rel="nofollow"}. We rebuild and deploy changes to the documentation to a [staged version](https://docs.powertools.aws.dev/lambda/python/stage/){target="_blank" rel="nofollow"}. This gives us safety that our docs can always be rebuilt, and ready to release to production when needed. -* [**Update draft release**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/release-drafter.yml#L25){target="_blank" rel="nofollow"}. We use [Release Drafter](https://github.com/release-drafter/release-drafter){target="_blank" rel="nofollow"} to generate a portion of our release notes and to always keep a fresh draft upon changes. You can read our [thoughts on a good quality release notes here](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#drafting-release-notes){target="_blank" rel="nofollow"} (human readable changes + automation). +* [**End-to-end tests**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/run-e2e-tests.yml#L41){target="_blank"}. We run E2E with a [high degree of parallelization](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#test-runner-parallelization). While it is designed to also run locally, it may incur AWS charges to contributors. For additional security, all infrastructure is ephemeral per change and per Python version. +* [**SAST check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/codeql-analysis.yml#L20){target="_blank"}. GitHub CodeQL runs ~30m static analysis in the entire codebase. +* [**Security posture check**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/ossf_scorecard.yml#L14){target="_blank"}. OSSF Scorecard runs numerous automated checks upon changes, and raises security alerts if [OSSF security practices](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank" rel="nofollow"} are no longer followed. +* [**Rebuild Changelog**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/build_changelog.yml#L23){target="_blank"}. We rebuild our entire changelog upon changes and create a PR for maintainers. This has the added benefit in keeping a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches){target="_blank" rel="nofollow"} while keeping removing error-prone tasks from maintainers. +* [**Stage documentation**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/on_push_docs.yml#L27C16-L27C16){target="_blank"}. We rebuild and deploy changes to the documentation to a [staged version](https://docs.powertools.aws.dev/lambda/python/stage/){target="_blank"}. This gives us safety that our docs can always be rebuilt, and ready to release to production when needed. +* [**Update draft release**](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/.github/workflows/release-drafter.yml#L25){target="_blank"}. We use [Release Drafter](https://github.com/release-drafter/release-drafter){target="_blank" rel="nofollow"} to generate a portion of our release notes and to always keep a fresh draft upon changes. You can read our [thoughts on a good quality release notes here](https://github.com/aws-powertools/powertools-lambda-python/blob/0523ff64606514ea3e59c07c8c69c83d751f61fa/MAINTAINERS.md#drafting-release-notes){target="_blank"} (human readable changes + automation). ## Continuous deployment practices !!! note "We adhere to industry recommendations from the [OSSF Scorecard project](https://bestpractices.coreinfrastructure.org/en/criteria){target="_blank" rel="nofollow"}, among [others](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions){target="_blank" rel="nofollow"}." -Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank" rel="nofollow"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. +Releases are triggered by maintainers along with a reviewer - [detailed info here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md#releasing-a-new-version){target="_blank"}. In addition to [checks that run for every code change](#continuous-integration-practices), our pipeline requires a manual approval before releasing. We use a combination of provenance and signed attestation for our builds, source code sealing, SAST scanners, Python specific static code analysis, ephemeral credentials that last a given job step, and more. diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 720432dd3c1..708a9de6855 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -9,19 +9,19 @@ Event handler for Amazon API Gateway REST and HTTP APIs, Application Loader Bala * Lightweight routing to reduce boilerplate for API Gateway REST/HTTP API, ALB and Lambda Function URLs. * Support for CORS, binary and Gzip compression, Decimals JSON encoding and bring your own JSON serializer -* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank" rel="nofollow"} for self-documented event schema +* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"} for self-documented event schema ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. ### Required resources -If you're using any API Gateway integration, you must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank" rel="nofollow"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank" rel="nofollow"} configured to invoke your Lambda function. +If you're using any API Gateway integration, you must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank"} configured to invoke your Lambda function. -In case of using [VPC Lattice](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank" rel="nofollow"}, you must have a service network configured to invoke your Lambda function. +In case of using [VPC Lattice](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"}, you must have a service network configured to invoke your Lambda function. This is the sample infrastructure for API Gateway and Lambda Function URLs we are using for the examples in this documentation. @@ -105,7 +105,7 @@ When using Amazon Application Load Balancer (ALB) to front your Lambda functions #### Lambda Function URL -When using [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html){target="_blank" rel="nofollow"}, you can use `LambdaFunctionUrlResolver`. +When using [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html){target="_blank"}, you can use `LambdaFunctionUrlResolver`. === "getting_started_lambda_function_url_resolver.py" @@ -121,7 +121,7 @@ When using [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/d #### VPC Lattice -When using [VPC Lattice with AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank" rel="nofollow"}, you can use `VPCLatticeResolver`. +When using [VPC Lattice with AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"}, you can use `VPCLatticeResolver`. === "getting_started_vpclattice_resolver.py" @@ -210,7 +210,7 @@ If you need to accept multiple HTTP methods in a single function, you can use th ### Accessing request details -Event Handler integrates with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank" rel="nofollow"}, and it exposes their respective resolver request details and convenient methods under `app.current_event`. +Event Handler integrates with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"}, and it exposes their respective resolver request details and convenient methods under `app.current_event`. That is why you see `app.resolve(event, context)` in every example. This allows Event Handler to resolve requests, and expose data like `app.lambda_context` and `app.current_event`. @@ -268,11 +268,11 @@ We provide pre-defined errors for the most popular ones such as HTTP 400, 401, 4 ### Custom Domain API Mappings -When using [Custom Domain API Mappings feature](https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html){target="_blank" rel="nofollow"}, you must use **`strip_prefixes`** param in the `APIGatewayRestResolver` constructor. +When using [Custom Domain API Mappings feature](https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html){target="_blank"}, you must use **`strip_prefixes`** param in the `APIGatewayRestResolver` constructor. **Scenario**: You have a custom domain `api.mydomain.dev`. Then you set `/payment` API Mapping to forward any payment requests to your Payments API. -**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/aws-powertools/powertools-lambda-roadmap/issues/34){target="_blank" rel="nofollow"}. +**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/aws-powertools/powertools-lambda-roadmap/issues/34){target="_blank"}. To address this API Gateway behavior, we use `strip_prefixes` parameter to account for these prefixes that are now injected into the path regardless of which type of API Gateway you're using. @@ -363,7 +363,7 @@ You can use the `Response` class to have full control over the response. For exa Some event sources require headers and cookies to be encoded as `multiValueHeaders`. ???+ warning "Using multiple values for HTTP headers in ALB?" - Make sure you [enable the multi value headers feature](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers){target="_blank" rel="nofollow"} to serialize response headers correctly. + Make sure you [enable the multi value headers feature](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers){target="_blank"} to serialize response headers correctly. === "fine_grained_responses.py" @@ -448,7 +448,7 @@ Like `compress` feature, the client must send the `Accept` header with the corre ### Debug mode -You can enable debug mode via `debug` param, or via `POWERTOOLS_DEV` [environment variable](../../index.md#environment-variables){target="_blank" rel="nofollow"}. +You can enable debug mode via `debug` param, or via `POWERTOOLS_DEV` [environment variable](../../index.md#environment-variables){target="_blank"}. This will enable full tracebacks errors in the response, print request and responses, and set CORS in development mode. @@ -602,7 +602,7 @@ _**Benefits**_ _**Downsides**_ -* **Cold starts**. Frequent deployments and/or high load can diminish the benefit of monolithic functions depending on your latency requirements, due to [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank" rel="nofollow"}. Always load test to pragmatically balance between your customer experience and development cognitive load. +* **Cold starts**. Frequent deployments and/or high load can diminish the benefit of monolithic functions depending on your latency requirements, due to [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank"}. Always load test to pragmatically balance between your customer experience and development cognitive load. * **Granular security permissions**. The micro function approach enables you to use fine-grained permissions & access controls, separate external dependencies & code signing at the function level. Conversely, you could have multiple functions while duplicating the final code artifact in a monolithic approach. * Regardless, least privilege can be applied to either approaches. * **Higher risk per deployment**. A misconfiguration or invalid import can cause disruption if not caught earlier in automated testing. Multiple functions can mitigate misconfigurations but they would still share the same code artifact. You can further minimize risks with multiple environments in your CI/CD pipeline. @@ -615,13 +615,13 @@ A micro function means that your final code artifact will be different to each f **Benefits** -* **Granular scaling**. A micro function can benefit from the [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank" rel="nofollow"} to scale differently depending on each part of your application. Concurrency controls and provisioned concurrency can also be used at a granular level for capacity management. +* **Granular scaling**. A micro function can benefit from the [Lambda scaling model](https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html){target="_blank"} to scale differently depending on each part of your application. Concurrency controls and provisioned concurrency can also be used at a granular level for capacity management. * **Discoverability**. Micro functions are easier do visualize when using distributed tracing. Their high-level architectures can be self-explanatory, and complexity is highly visible — assuming each function is named to the business purpose it serves. -* **Package size**. An independent function can be significant smaller (KB vs MB) depending on external dependencies it require to perform its purpose. Conversely, a monolithic approach can benefit from [Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html){target="_blank" rel="nofollow"} to optimize builds for external dependencies. +* **Package size**. An independent function can be significant smaller (KB vs MB) depending on external dependencies it require to perform its purpose. Conversely, a monolithic approach can benefit from [Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html){target="_blank"} to optimize builds for external dependencies. **Downsides** -* **Upfront investment**. You need custom build tooling to bundle assets, including [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank" rel="nofollow"}. Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes. +* **Upfront investment**. You need custom build tooling to bundle assets, including [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank"}. Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes. * Engineering discipline is necessary for both approaches. Micro-function approach however requires further attention in consistency as the number of functions grow, just like any distributed system. * **Harder to share code**. Shared code must be carefully evaluated to avoid unnecessary deployments when that changes. Equally, if shared code isn't a library, your development, building, deployment tooling need to accommodate the distinct layout. diff --git a/docs/core/event_handler/appsync.md b/docs/core/event_handler/appsync.md index b0f8a294ebd..789bf788004 100644 --- a/docs/core/event_handler/appsync.md +++ b/docs/core/event_handler/appsync.md @@ -9,15 +9,15 @@ Event handler for AWS AppSync Direct Lambda Resolver and Amplify GraphQL Transfo * Automatically parse API arguments to function arguments * Choose between strictly match a GraphQL field name or all of them to a function -* Integrates with [Data classes utilities](../../utilities/data_classes.md){target="_blank" rel="nofollow"} to access resolver and identity information +* Integrates with [Data classes utilities](../../utilities/data_classes.md){target="_blank"} to access resolver and identity information * Works with both Direct Lambda Resolver and Amplify GraphQL Transformer `@function` directive * Support async Python 3.8+ functions, and generators ## Terminology -**[Direct Lambda Resolver](https://docs.aws.amazon.com/appsync/latest/devguide/direct-lambda-reference.html){target="_blank" rel="nofollow"}**. A custom AppSync Resolver to bypass the use of Apache Velocity Template (VTL) and automatically map your function's response to a GraphQL field. +**[Direct Lambda Resolver](https://docs.aws.amazon.com/appsync/latest/devguide/direct-lambda-reference.html){target="_blank"}**. A custom AppSync Resolver to bypass the use of Apache Velocity Template (VTL) and automatically map your function's response to a GraphQL field. -**[Amplify GraphQL Transformer](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank" rel="nofollow"}**. Custom GraphQL directives to define your application's data model using Schema Definition Language (SDL). Amplify CLI uses these directives to convert GraphQL SDL into full descriptive AWS CloudFormation templates. +**[Amplify GraphQL Transformer](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank"}**. Custom GraphQL directives to define your application's data model using Schema Definition Language (SDL). Amplify CLI uses these directives to convert GraphQL SDL into full descriptive AWS CloudFormation templates. ## Getting started @@ -28,7 +28,7 @@ You must have an existing AppSync GraphQL API and IAM permissions to invoke your This is the sample infrastructure we are using for the initial examples with a AppSync Direct Lambda Resolver. ???+ tip "Tip: Designing GraphQL Schemas for the first time?" - Visit [AWS AppSync schema documentation](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html){target="_blank" rel="nofollow"} for understanding how to define types, nesting, and pagination. + Visit [AWS AppSync schema documentation](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html){target="_blank"} for understanding how to define types, nesting, and pagination. === "getting_started_schema.graphql" @@ -93,7 +93,7 @@ Here's an example with two separate functions to resolve `getTodo` and `listTodo ### Scalar functions -When working with [AWS AppSync Scalar types](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html){target="_blank" rel="nofollow"}, you might want to generate the same values for data validation purposes. +When working with [AWS AppSync Scalar types](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html){target="_blank"}, you might want to generate the same values for data validation purposes. For convenience, the most commonly used values are available as functions within `scalar_types_utils` module. @@ -143,7 +143,7 @@ For Lambda Python3.8+ runtime, this utility supports async functions when you us ### Amplify GraphQL Transformer -Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/install){target="_blank" rel="nofollow"}, create a new API using `amplify add api` and use the following GraphQL Schema. +Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/install){target="_blank"}, create a new API using `amplify add api` and use the following GraphQL Schema. @@ -151,7 +151,7 @@ Assuming you have [Amplify CLI installed](https://docs.amplify.aws/cli/start/ins --8<-- "examples/event_handler_graphql/src/amplify_graphql_transformer_schema.graphql" ``` -[Create two new basic Python functions](https://docs.amplify.aws/cli/function#set-up-a-function){target="_blank" rel="nofollow"} via `amplify add function`. +[Create two new basic Python functions](https://docs.amplify.aws/cli/function#set-up-a-function){target="_blank"} via `amplify add function`. ???+ note Amplify CLI generated functions use `Pipenv` as a dependency manager. Your function source code is located at **`amplify/backend/function/your-function-name`**. @@ -192,7 +192,7 @@ Use the following code for `merchantInfo` and `searchMerchant` functions respect ### Custom data models -You can subclass [AppSyncResolverEvent](../../utilities/data_classes.md#appsync-resolver){target="_blank" rel="nofollow"} to bring your own set of methods to handle incoming events, by using `data_model` param in the `resolve` method. +You can subclass [AppSyncResolverEvent](../../utilities/data_classes.md#appsync-resolver){target="_blank"} to bring your own set of methods to handle incoming events, by using `data_model` param in the `resolve` method. === "custom_models.py.py" @@ -215,7 +215,7 @@ You can subclass [AppSyncResolverEvent](../../utilities/data_classes.md#appsync- ### Split operations with Router ???+ tip - Read the **[considerations section for trade-offs between monolithic and micro functions](./api_gateway.md#considerations){target="_blank" rel="nofollow"}**, as it's also applicable here. + Read the **[considerations section for trade-offs between monolithic and micro functions](./api_gateway.md#considerations){target="_blank"}**, as it's also applicable here. As you grow the number of related GraphQL operations a given Lambda function should handle, it is natural to split them into separate files to ease maintenance - That's when the `Router` feature comes handy. diff --git a/docs/core/logger.md b/docs/core/logger.md index 20accabb310..30a43a5817c 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -15,7 +15,7 @@ Logger provides an opinionated logger with output structured as JSON. ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. Logger requires two settings: @@ -39,7 +39,7 @@ Your Logger will include the following keys to your structured logging: | **message**: `Any` | `Collecting payment` | Unserializable JSON values are casted as `str` | | **timestamp**: `str` | `2021-05-03 10:20:19,650+0200` | Timestamp with milliseconds, by default uses local timezone | | **service**: `str` | `payment` | Service name defined, by default `service_undefined` | -| **xray_trace_id**: `str` | `1-5759e988-bd862e3fe1be46a994272793` | When [tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank" rel="nofollow"}, it shows X-Ray Trace ID | +| **xray_trace_id**: `str` | `1-5759e988-bd862e3fe1be46a994272793` | When [tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"}, it shows X-Ray Trace ID | | **sampling_rate**: `float` | `0.1` | When enabled, it shows sampling rate in percentage e.g. 10% | | **exception_name**: `str` | `ValueError` | When `logger.exception` is used and there is an exception | | **exception**: `str` | `Traceback (most recent call last)..` | When `logger.exception` is used and there is an exception | @@ -108,7 +108,7 @@ You can set a Correlation ID using `correlation_id_path` param by passing a [JME #### set_correlation_id method -You can also use `set_correlation_id` method to inject it anywhere else in your code. Example below uses [Event Source Data Classes utility](../utilities/data_classes.md){target="_blank" rel="nofollow"} to easily access events properties. +You can also use `set_correlation_id` method to inject it anywhere else in your code. Example below uses [Event Source Data Classes utility](../utilities/data_classes.md){target="_blank"} to easily access events properties. === "set_correlation_id_method.py" @@ -163,7 +163,7 @@ You can append additional keys using either mechanism: #### append_keys method ???+ warning - `append_keys` is not thread-safe, please see [RFC](https://github.com/aws-powertools/powertools-lambda-python/issues/991){target="_blank" rel="nofollow"}. + `append_keys` is not thread-safe, please see [RFC](https://github.com/aws-powertools/powertools-lambda-python/issues/991){target="_blank"}. You can append your own keys to your existing Logger via `append_keys(**additional_key_values)` method. @@ -242,7 +242,7 @@ You can remove any additional key from Logger state using `remove_keys`. #### Clearing all 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" rel="nofollow"}, this means that custom keys can be persisted across invocations. If you want all custom keys to be deleted, you can use `clear_state=True` param in `inject_lambda_context` decorator. +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 `clear_state=True` param in `inject_lambda_context` decorator. ???+ tip "Tip: When is this useful?" It is useful when you add multiple custom keys conditionally, instead of setting a default `None` value if not present. Any key with `None` value is automatically removed by Logger. @@ -360,7 +360,7 @@ You can use any of the following built-in JMESPath expressions as part of [injec ### Reusing Logger across your code -Similar to [Tracer](./tracer.md#reusing-tracer-across-your-code){target="_blank" rel="nofollow"}, a new instance that uses the same `service` name - env var or explicit parameter - will reuse a previous Logger instance. Just like `logging.getLogger("logger_name")` would in the standard library if called with the same logger name. +Similar to [Tracer](./tracer.md#reusing-tracer-across-your-code){target="_blank"}, a new instance that uses the same `service` name - env var or explicit parameter - will reuse a previous Logger instance. Just like `logging.getLogger("logger_name")` would in the standard library if called with the same logger name. Notice in the CloudWatch Logs output how `payment_id` appeared as expected when logging in `collect.py`. @@ -407,7 +407,7 @@ You can use values ranging from `0.0` to `1` (100%) when setting `POWERTOOLS_LOG Sampling decision happens at the Logger initialization. This means sampling may happen significantly more or less than depending on your traffic patterns, for example a steady low number of invocations and thus few cold starts. ???+ note - Open a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank" rel="nofollow"} if you want Logger to calculate sampling for every invocation + Open a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank"} if you want Logger to calculate sampling for every invocation === "sampling_debug_logs.py" @@ -449,7 +449,7 @@ If you prefer configuring it separately, or you'd want to bring this JSON Format !!! note "In this context, an observability provider is an [AWS Lambda Partner](https://go.aws/3HtU6CZ){target="_blank" rel="nofollow"} offering a platform for logging, metrics, traces, etc." -You can send logs to the observability provider of your choice via [Lambda Extensions](https://aws.amazon.com/blogs/compute/using-aws-lambda-extensions-to-send-logs-to-custom-destinations/){target="_blank" rel="nofollow"}. In most cases, you shouldn't need any custom Logger configuration, and logs will be shipped async without any performance impact. +You can send logs to the observability provider of your choice via [Lambda Extensions](https://aws.amazon.com/blogs/compute/using-aws-lambda-extensions-to-send-logs-to-custom-destinations/){target="_blank"}. In most cases, you shouldn't need any custom Logger configuration, and logs will be shipped async without any performance impact. #### Built-in formatters @@ -744,4 +744,4 @@ Here's an example where we persist `payment_id` not `request_id`. Note that `pay ### How do I aggregate and search Powertools for AWS Lambda (Python) logs across accounts? -As of now, ElasticSearch (ELK) or 3rd party solutions are best suited to this task. Please refer to this [discussion for more details](https://github.com/aws-powertools/powertools-lambda-python/issues/460){target="_blank" rel="nofollow"} +As of now, ElasticSearch (ELK) or 3rd party solutions are best suited to this task. Please refer to this [discussion for more details](https://github.com/aws-powertools/powertools-lambda-python/issues/460){target="_blank"} diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 289068aeeeb..63ee307e789 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -3,9 +3,9 @@ title: Metrics description: Core utility --- -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){target="_blank" rel="nofollow"}. +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){target="_blank"}. -These metrics can be visualized through [Amazon CloudWatch Console](https://console.aws.amazon.com/cloudwatch/){target="_blank" rel="nofollow"}. +These metrics can be visualized through [Amazon CloudWatch Console](https://console.aws.amazon.com/cloudwatch/){target="_blank"}. ## Key features @@ -22,7 +22,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar * **Dimensions**. Metrics metadata in key-value format. They help you slice and dice metrics visualization, for example `ColdStart` metric by Payment `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 [here](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics){target="_blank" rel="nofollow"}. +* **Resolution**. It's a value representing the storage resolution for the corresponding metric. Metrics can be either Standard or High resolution. Read more [here](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics){target="_blank"}.
@@ -32,7 +32,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. Metric has two global settings that will be used across all metrics emitted: @@ -83,7 +83,7 @@ You can create metrics using `add_metric`, and you can create dimensions for all ### Adding high-resolution metrics -You can create [high-resolution metrics](https://aws.amazon.com/about-aws/whats-new/2023/02/amazon-cloudwatch-high-resolution-metric-extraction-structured-logs/){target="_blank" rel="nofollow"} passing `resolution` parameter to `add_metric`. +You can create [high-resolution metrics](https://aws.amazon.com/about-aws/whats-new/2023/02/amazon-cloudwatch-high-resolution-metric-extraction-structured-logs/){target="_blank"} passing `resolution` parameter to `add_metric`. ???+ tip "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. @@ -154,7 +154,7 @@ This decorator also **validates**, **serializes**, and **flushes** all your metr * Maximum of 29 user-defined dimensions * Namespace is set, and no more than one - * Metric units must be [supported by CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank" rel="nofollow"} + * Metric units must be [supported by CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank"} #### Raising SchemaValidationError on empty metrics @@ -191,7 +191,7 @@ If it's a cold start invocation, this feature will: This has the advantage of keeping cold start metric separate from your application metrics, where you might have unrelated dimensions. ???+ info - We do not emit 0 as a value for ColdStart metric for cost reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank" rel="nofollow"} if you'd prefer a flag to override it. + We do not emit 0 as a value for ColdStart metric for cost reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank"} if you'd prefer a flag to override it. ## Advanced @@ -219,7 +219,7 @@ You can add high-cardinality data as part of your Metrics log with `add_metadata CloudWatch EMF uses the same dimensions across all your metrics. Use `single_metric` if you have a metric that should have different dimensions. ???+ info - Generally, this would be an edge case since you [pay for unique metric](https://aws.amazon.com/cloudwatch/pricing){target="_blank" rel="nofollow"}. Keep the following formula in mind: + Generally, this would be an edge case since you [pay for unique metric](https://aws.amazon.com/cloudwatch/pricing){target="_blank"}. Keep the following formula in mind: **unique metric = (metric_name + dimension_name + dimension_value)** @@ -282,17 +282,17 @@ You can use `EphemeralMetrics` class when looking to isolate multiple instances !!! question "Why not changing the default `Metrics` behaviour to not share data across instances?" -This is an intentional design to prevent accidental data deduplication or data loss issues due to [CloudWatch EMF](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank" rel="nofollow"} metric dimension constraint. +This is an intentional design to prevent accidental data deduplication or data loss issues due to [CloudWatch EMF](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank"} metric dimension constraint. -In CloudWatch, there are two metric ingestion mechanisms: [EMF (async)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank" rel="nofollow"} and [`PutMetricData` API (sync)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data){target="_blank" rel="nofollow"}. +In CloudWatch, there are two metric ingestion mechanisms: [EMF (async)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="_blank"} and [`PutMetricData` API (sync)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data){target="_blank"}. The former creates metrics asynchronously via CloudWatch Logs, and the latter uses a synchronous and more flexible ingestion API. !!! important "Key concept" - CloudWatch [considers a metric unique](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Metric){target="_blank" rel="nofollow"} by a combination of metric **name**, metric **namespace**, and zero or more metric **dimensions**. + CloudWatch [considers a metric unique](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Metric){target="_blank"} by a combination of metric **name**, metric **namespace**, and zero or more metric **dimensions**. -With EMF, metric dimensions are shared with any metrics you define. With `PutMetricData` API, you can set a [list](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank" rel="nofollow"} defining one or more metrics with distinct dimensions. +With EMF, metric dimensions are shared with any metrics you define. With `PutMetricData` API, you can set a [list](https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html){target="_blank"} defining one or more metrics with distinct dimensions. This is a subtle yet important distinction. Imagine you had the following metrics to emit: @@ -374,4 +374,4 @@ You can read standard output and assert whether metrics have been flushed. Here' ``` ???+ tip - For more elaborate assertions and comparisons, check out [our functional testing for Metrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/test_metrics.py){target="_blank" rel="nofollow"} + For more elaborate assertions and comparisons, check out [our functional testing for Metrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/test_metrics.py){target="_blank"} diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 6ffd44d3be0..413434718db 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -17,19 +17,19 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github. ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. !!! note "Tracer relies on AWS X-Ray SDK over [OpenTelememetry Distro (ADOT)](https://aws-otel.github.io/docs/getting-started/lambda){target="_blank" rel="nofollow"} for optimal cold start (lower latency)." ### Install -!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank" rel="nofollow"}" +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" Add `aws-lambda-powertools[tracer]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Tracer. ### Permissions -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){target="_blank" rel="nofollow"} to send traces to AWS X-Ray. +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){target="_blank"} to send traces to AWS X-Ray. ```yaml hl_lines="9 12" title="AWS Serverless Application Model (SAM) example" --8<-- "examples/tracer/sam/template.yaml" @@ -51,7 +51,7 @@ You can quickly start by initializing `Tracer` and use `capture_lambda_handler` ### Annotations & Metadata -**Annotations** are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to create [Trace Groups](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-xray-adds-the-ability-to-group-traces/){target="_blank" rel="nofollow"} to slice and dice your transactions. +**Annotations** are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to create [Trace Groups](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-xray-adds-the-ability-to-group-traces/){target="_blank"} to slice and dice your transactions. ```python hl_lines="8" title="Adding annotations with put_annotation method" --8<-- "examples/tracer/src/put_trace_annotations.py" @@ -107,7 +107,7 @@ You can trace asynchronous functions and generator functions (including context ### Patching modules -Tracer automatically patches all [supported libraries by X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-python-patching.html){target="_blank" rel="nofollow"} during initialization, by default. Underneath, AWS X-Ray SDK checks whether a supported library has been imported before patching. +Tracer automatically patches all [supported libraries by X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-python-patching.html){target="_blank"} during initialization, by default. Underneath, AWS X-Ray SDK checks whether a supported library has been imported before patching. If you're looking to shave a few microseconds, or milliseconds depending on your function memory configuration, you can patch specific modules using `patch_modules` param: @@ -172,7 +172,7 @@ You can use `aiohttp_trace_config` function to create a valid [aiohttp trace_con You can use `tracer.provider` attribute to access all methods provided by AWS X-Ray `xray_recorder` object. -This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example [thread-safe](https://github.com/aws/aws-xray-sdk-python/#user-content-trace-threadpoolexecutor){target="_blank" rel="nofollow"}, or [context managers](https://github.com/aws/aws-xray-sdk-python/#user-content-start-a-custom-segmentsubsegment){target="_blank" rel="nofollow"}. +This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example [thread-safe](https://github.com/aws/aws-xray-sdk-python/#user-content-trace-threadpoolexecutor){target="_blank"}, or [context managers](https://github.com/aws/aws-xray-sdk-python/#user-content-start-a-custom-segmentsubsegment){target="_blank"}. ```python hl_lines="14" title="Tracing a code block with in_subsegment escape hatch" --8<-- "examples/tracer/src/sdk_escape_hatch.py" @@ -181,7 +181,7 @@ This is useful when you need a feature available in X-Ray that is not available ### Concurrent asynchronous functions ???+ warning - [X-Ray SDK will raise an exception](https://github.com/aws/aws-xray-sdk-python/issues/164){target="_blank" rel="nofollow"} when async functions are run and traced concurrently + [X-Ray SDK will raise an exception](https://github.com/aws/aws-xray-sdk-python/issues/164){target="_blank"} when async functions are run and traced concurrently A safe workaround mechanism is to use `in_subsegment_async` available via Tracer escape hatch (`tracer.provider`). @@ -221,4 +221,4 @@ Tracer is disabled by default when not running in the AWS Lambda environment - T * Use annotations on key operations to slice and dice traces, create unique views, and create metrics from it via Trace Groups * Use a namespace when adding metadata to group data more easily -* Annotations and metadata are added to the current subsegment opened. If you want them in a specific subsegment, use a [context manager](https://github.com/aws/aws-xray-sdk-python/#start-a-custom-segmentsubsegment){target="_blank" rel="nofollow"} via the escape hatch mechanism +* Annotations and metadata are added to the current subsegment opened. If you want them in a specific subsegment, use a [context manager](https://github.com/aws/aws-xray-sdk-python/#start-a-custom-segmentsubsegment){target="_blank"} via the escape hatch mechanism diff --git a/docs/index.md b/docs/index.md index e6d262f62e6..d0269260711 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,15 +8,15 @@ description: Powertools for AWS Lambda (Python) Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity. ???+ tip - Powertools for AWS Lambda (Python) is also available for [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank" rel="nofollow"}, [TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/){target="_blank" rel="nofollow"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank" rel="nofollow"} + Powertools for AWS Lambda (Python) is also available for [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank"}, [TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/){target="_blank" }, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} ??? hint "Support this project by becoming a reference customer, sharing your work, or using Layers/SAR :heart:" You can choose to support us in three ways: - 1) [**Become a reference customer**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank" rel="nofollow"}. This gives us permission to list your company in our documentation. + 1) [**Become a reference customer**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank"}. This gives us permission to list your company in our documentation. - 2) [**Share your work**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank" rel="nofollow"}. Blog posts, video, sample projects you used Powertools! + 2) [**Share your work**](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=community-content&template=share_your_work.yml&title=%5BI+Made+This%5D%3A+%3CTITLE%3E){target="_blank"}. Blog posts, video, sample projects you used Powertools! 3) Use [**Lambda Layers**](#lambda-layer) or [**SAR**](#sar), if possible. This helps us understand who uses Powertools for AWS Lambda (Python) in a non-intrusive way, and helps us gain future investments for other Powertools for AWS Lambda languages. @@ -33,7 +33,7 @@ You can install Powertools for AWS Lambda (Python) using one of the following op !!! question "Looking for Pip signed releases? [Learn more about verifying signed builds](./security.md#verifying-signed-builds)" ??? question "Using Pip? You might need to install additional dependencies." - [**Tracer**](./core/tracer.md){target="_blank" rel="nofollow"}, [**Validation**](./utilities/validation.md){target="_blank" rel="nofollow"} and [**Parser**](./utilities/parser.md){target="_blank" rel="nofollow"} require additional dependencies. If you prefer to install all of them, use [**`pip install "aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard:. + [**Tracer**](./core/tracer.md){target="_blank"}, [**Validation**](./utilities/validation.md){target="_blank"} and [**Parser**](./utilities/parser.md){target="_blank"} require additional dependencies. If you prefer to install all of them, use [**`pip install "aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard:. For example: @@ -46,7 +46,7 @@ You can install Powertools for AWS Lambda (Python) using one of the following op !!! info "Using Lambda Layer? Simply add [**`"aws-lambda-powertools[all]"`**](#){: .copyMe}:clipboard: as a development dependency." -Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank" rel="nofollow"}. This helps us achieve an optimal package size and initialization. However, when developing locally, you need to install AWS SDK as a development dependency (not as a production dependency): +Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank"}. This helps us achieve an optimal package size and initialization. However, when developing locally, you need to install AWS SDK as a development dependency (not as a production dependency): * **Pip**: [**`pip install "aws-lambda-powertools[aws-sdk]"`**](#){: .copyMe}:clipboard: * **Poetry**: [**`poetry add "aws-lambda-powertools[aws-sdk]" --group dev`**](#){: .copyMe}:clipboard: @@ -55,24 +55,24 @@ Powertools for AWS Lambda (Python) relies on the [AWS SDK bundled in the Lambda ??? question "Why is that necessary?" Powertools for AWS Lambda (Python) relies on the AWS SDK being available to use in the target runtime (AWS Lambda). - As a result, it affects your favorite IDE in terms of code auto-completion, or running your tests suite locally with no Lambda emulation such as [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html){target="_blank" rel="nofollow"}. + As a result, it affects your favorite IDE in terms of code auto-completion, or running your tests suite locally with no Lambda emulation such as [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html){target="_blank"}. **A word about dependency resolution** In this context, `[aws-sdk]` is an alias to the `boto3` package. Due to dependency resolution, it'll either install: -* **(A)** the SDK version available in [Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank" rel="nofollow"} -* **(B)** a more up-to-date version if another package you use also depends on `boto3`, for example [Powertools for AWS Lambda (Python) Tracer](core/tracer.md){target="_blank" rel="nofollow"} +* **(A)** the SDK version available in [Lambda runtime](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html){target="_blank"} +* **(B)** a more up-to-date version if another package you use also depends on `boto3`, for example [Powertools for AWS Lambda (Python) Tracer](core/tracer.md){target="_blank"} ### Lambda Layer ???+ warning "As of now, Container Image deployment (OCI) or inline Lambda functions do not support Lambda Layers." -[Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html){target="_blank" rel="nofollow"} is a .zip file archive that can contain additional code, pre-packaged dependencies, data, or configuration files. Layers promote code sharing and separation of responsibilities so that you can iterate faster on writing business logic. +[Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html){target="_blank"} is a .zip file archive that can contain additional code, pre-packaged dependencies, data, or configuration files. Layers promote code sharing and separation of responsibilities so that you can iterate faster on writing business logic. -For our Layers, we compile and optimize [all dependencies](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/pyproject.toml#L98){target="_blank" rel="nofollow"}, and [remove duplicate dependencies already available in the Lambda runtime](https://github.com/awslabs/cdk-aws-lambda-powertools-layer/blob/main/layer/Python/Dockerfile#L36){target="_blank" rel="nofollow"} to achieve the most optimal size. +For our Layers, we compile and optimize [all dependencies](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/pyproject.toml#L98){target="_blank"}, and [remove duplicate dependencies already available in the Lambda runtime](https://github.com/awslabs/cdk-aws-lambda-powertools-layer/blob/main/layer/Python/Dockerfile#L36){target="_blank"} to achieve the most optimal size. -You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambda Console](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-using){target="_blank" rel="nofollow"}, or your preferred deployment framework. +You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambda Console](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-using){target="_blank"}, or your preferred deployment framework. ??? note "Note: Click to expand and copy any regional Lambda Layer ARN" @@ -464,8 +464,8 @@ Compared with the [public Layer ARN](#lambda-layer) option, SAR allows you to ch | App | ARN | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | -| [aws-lambda-powertools-python-layer](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer){target="_blank" rel="nofollow"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). | -| [aws-lambda-powertools-python-layer-arm64](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer-arm64){target="_blank" rel="nofollow"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer-arm64](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). For arm64 functions. | +| [aws-lambda-powertools-python-layer](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer){target="_blank"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). | +| [aws-lambda-powertools-python-layer-arm64](https://serverlessrepo.aws.amazon.com/applications/eu-west-1/057560766410/aws-lambda-powertools-python-layer-arm64){target="_blank"} | [arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer-arm64](#){: .copyMe}:clipboard: | Contains all extra dependencies (e.g: pydantic). For arm64 functions. | ??? note "Click to expand and copy SAR code snippets for popular frameworks" @@ -681,21 +681,21 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai | Utility | Description | | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [**Tracing**](./core/tracer.md){target="_blank" rel="nofollow"} | Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions | -| [**Logger**](./core/logger.md){target="_blank" rel="nofollow"} | Structured logging made easier, and decorator to enrich structured logging with key Lambda context details | -| [**Metrics**](./core/metrics.md){target="_blank" rel="nofollow"} | Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF) | -| [**Event handler: AppSync**](./core/event_handler/appsync.md){target="_blank" rel="nofollow"} | AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function | +| [**Tracing**](./core/tracer.md){target="_blank"} | Decorators and utilities to trace Lambda function handlers, and both synchronous and asynchronous functions | +| [**Logger**](./core/logger.md){target="_blank"} | Structured logging made easier, and decorator to enrich structured logging with key Lambda context details | +| [**Metrics**](./core/metrics.md){target="_blank"} | Custom Metrics created asynchronously via CloudWatch Embedded Metric Format (EMF) | +| [**Event handler: AppSync**](./core/event_handler/appsync.md){target="_blank"} | AppSync event handler for Lambda Direct Resolver and Amplify GraphQL Transformer function | | [**Event handler: API Gateway, ALB and Lambda Function URL**](https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/) | Amazon API Gateway REST/HTTP API and ALB event handler for Lambda functions invoked using Proxy integration, and Lambda Function URL | -| [**Middleware factory**](./utilities/middleware_factory.md){target="_blank" rel="nofollow"} | Decorator factory to create your own middleware to run logic before, and after each Lambda invocation | -| [**Parameters**](./utilities/parameters.md){target="_blank" rel="nofollow"} | Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time | -| [**Batch processing**](./utilities/batch.md){target="_blank" rel="nofollow"} | Handle partial failures for AWS SQS batch processing | -| [**Typing**](./utilities/typing.md){target="_blank" rel="nofollow"} | Static typing classes to speedup development in your IDE | -| [**Validation**](./utilities/validation.md){target="_blank" rel="nofollow"} | JSON Schema validator for inbound events and responses | -| [**Event source data classes**](./utilities/data_classes.md){target="_blank" rel="nofollow"} | Data classes describing the schema of common Lambda event triggers | -| [**Parser**](./utilities/parser.md){target="_blank" rel="nofollow"} | Data parsing and deep validation using Pydantic | -| [**Idempotency**](./utilities/idempotency.md){target="_blank" rel="nofollow"} | Idempotent Lambda handler | -| [**Feature Flags**](./utilities/feature_flags.md){target="_blank" rel="nofollow"} | A simple rule engine to evaluate when one or multiple features should be enabled depending on the input | -| [**Streaming**](./utilities/streaming.md){target="_blank" rel="nofollow"} | Streams datasets larger than the available memory as streaming data. | +| [**Middleware factory**](./utilities/middleware_factory.md){target="_blank"} | Decorator factory to create your own middleware to run logic before, and after each Lambda invocation | +| [**Parameters**](./utilities/parameters.md){target="_blank"} | Retrieve parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, or Amazon DynamoDB, and cache them for a specific amount of time | +| [**Batch processing**](./utilities/batch.md){target="_blank"} | Handle partial failures for AWS SQS batch processing | +| [**Typing**](./utilities/typing.md){target="_blank"} | Static typing classes to speedup development in your IDE | +| [**Validation**](./utilities/validation.md){target="_blank"} | JSON Schema validator for inbound events and responses | +| [**Event source data classes**](./utilities/data_classes.md){target="_blank"} | Data classes describing the schema of common Lambda event triggers | +| [**Parser**](./utilities/parser.md){target="_blank"} | Data parsing and deep validation using Pydantic | +| [**Idempotency**](./utilities/idempotency.md){target="_blank"} | Idempotent Lambda handler | +| [**Feature Flags**](./utilities/feature_flags.md){target="_blank"} | A simple rule engine to evaluate when one or multiple features should be enabled depending on the input | +| [**Streaming**](./utilities/streaming.md){target="_blank"} | Streams datasets larger than the available memory as streaming data. | ## Environment variables @@ -705,18 +705,18 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai | Environment variable | Description | Utility | Default | | ----------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------- | | **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | `"service_undefined"` | -| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics){target="_blank" rel="nofollow"} | `None` | -| **POWERTOOLS_TRACE_DISABLED** | Explicitly disables tracing | [Tracing](./core/tracer){target="_blank" rel="nofollow"} | `false` | -| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer){target="_blank" rel="nofollow"} | `true` | -| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer){target="_blank" rel="nofollow"} | `true` | -| **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory){target="_blank" rel="nofollow"} | `false` | -| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger){target="_blank" rel="nofollow"} | `false` | -| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger){target="_blank" rel="nofollow"} | `0` | -| **POWERTOOLS_LOG_DEDUPLICATION_DISABLED** | Disables log deduplication filter protection to use Pytest Live Log feature | [Logging](./core/logger){target="_blank" rel="nofollow"} | `false` | -| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](./utilities/parameters/#adjusting-cache-ttl){target="_blank" rel="nofollow"} | `5` | -| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters/#ssmprovider){target="_blank" rel="nofollow"} | `false` | +| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics){target="_blank"} | `None` | +| **POWERTOOLS_TRACE_DISABLED** | Explicitly disables tracing | [Tracing](./core/tracer){target="_blank"} | `false` | +| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer){target="_blank"} | `true` | +| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer){target="_blank"} | `true` | +| **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory){target="_blank"} | `false` | +| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger){target="_blank"} | `false` | +| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger){target="_blank"} | `0` | +| **POWERTOOLS_LOG_DEDUPLICATION_DISABLED** | Disables log deduplication filter protection to use Pytest Live Log feature | [Logging](./core/logger){target="_blank"} | `false` | +| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](./utilities/parameters/#adjusting-cache-ttl){target="_blank"} | `5` | +| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters/#ssmprovider){target="_blank"} | `false` | | **POWERTOOLS_DEV** | Increases verbosity across utilities | Multiple; see [POWERTOOLS_DEV effect below](#optimizing-for-non-production-environments) | `false` | -| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger){target="_blank" rel="nofollow"} | `INFO` | +| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger){target="_blank"} | `INFO` | ### Optimizing for non-production environments @@ -743,7 +743,7 @@ When necessary, you can use `POWERTOOLS_DEBUG` environment variable to enable de ### 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 (Python), you can request to have your name and logo added to the README file by raising a [Support Powertools for AWS Lambda (Python) (become a reference)](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank" rel="nofollow"} 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 (Python), you can request to have your name and logo added to the README file by raising a [Support Powertools for AWS Lambda (Python) (become a reference)](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E){target="_blank"} issue. The following companies, among others, use Powertools: @@ -760,7 +760,7 @@ The following companies, among others, use Powertools: ### Sharing your work -Share what you did with Powertools for AWS Lambda (Python) 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools for AWS Lambda (Python) [here](https://docs.powertools.aws.dev/lambda/python/latest/we_made_this/){target="_blank" rel="nofollow"}. +Share what you did with Powertools for AWS Lambda (Python) 💞💞. Blog post, workshops, presentation, sample apps and others. Check out what the community has already shared about Powertools for AWS Lambda (Python) [here](https://docs.powertools.aws.dev/lambda/python/latest/we_made_this/){target="_blank"}. ### Using Lambda Layer or SAR diff --git a/docs/maintainers.md b/docs/maintainers.md index 061acbb4c8f..455d33f6d8a 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -9,7 +9,7 @@ description: Playbook for active maintainers in Powertools for AWS Lambda (Pytho !!! note "Please treat this content as a living document." -This is document explains who the maintainers are, their responsibilities, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CONTRIBUTING.md){target="_blank" rel="nofollow"}. +This is document explains who the maintainers are, their responsibilities, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CONTRIBUTING.md){target="_blank"}. ## Current Maintainers @@ -81,7 +81,7 @@ Be aware of recurring ambiguous situations and [document them](#common-scenarios ### Uphold Code of Conduct -Model the behavior set forward by the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank" rel="nofollow"} and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate behavior does not immediately fall within the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank" rel="nofollow"}. +Model the behavior set forward by the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank"} and raise any violations to other maintainers and admins. There could be unusual circumstances where inappropriate behavior does not immediately fall within the [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank"}. These might be nuanced and should be handled with extra care - when in doubt, do not engage and reach out to other maintainers and admins. @@ -89,7 +89,7 @@ These might be nuanced and should be handled with extra care - when in doubt, do Security is your number one priority. Maintainer's Github keys must be password protected securely and any reported security vulnerabilities are addressed before features or bugs. -Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/SECURITY.md){target="_blank" rel="nofollow"} for details. +Note that this repository is monitored and supported 24/7 by Amazon Security, see [Reporting a Vulnerability](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/SECURITY.md){target="_blank"} for details. ### Review Pull Requests @@ -97,7 +97,7 @@ Review pull requests regularly, comment, suggest, reject, merge and close. Accep PRs are [labeled](#labels) based on file changes and semantic title. Pay attention to whether labels reflect the current state of the PR and correct accordingly. -Use and enforce [semantic versioning](https://semver.org/) pull request titles, as these will be used for [CHANGELOG](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CHANGELOG.md){target="_blank" rel="nofollow"} and [Release notes](https://github.com/aws-powertools/powertools-lambda-python/releases) - make sure they communicate their intent at the human level. +Use and enforce [semantic versioning](https://semver.org/) pull request titles, as these will be used for [CHANGELOG](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CHANGELOG.md){target="_blank"} and [Release notes](https://github.com/aws-powertools/powertools-lambda-python/releases) - make sure they communicate their intent at the human level. > TODO: This is an area we want to automate using the new GitHub GraphQL API. @@ -289,7 +289,7 @@ Add integration checks that validate pull requests and pushes to ease the burden ### Negative Impact on the Project -Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank" rel="nofollow"} violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. +Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank"} violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. ### Becoming a maintainer @@ -315,7 +315,7 @@ When in doubt, use `need-more-information` or `need-customer-feedback` labels to ### Crediting contributions -We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-python/releases){target="_blank" rel="nofollow"} as an automated process. If you find contributors are missing from the release note you're producing, please add them manually. +We credit all contributions as part of each [release note](https://github.com/aws-powertools/powertools-lambda-python/releases){target="_blank"} as an automated process. If you find contributors are missing from the release note you're producing, please add them manually. ### Is that a bug? @@ -388,7 +388,7 @@ Where: ### Mechanics -Under [`BaseInfrastructure`](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/e2e/utils/infrastructure.py){target="_blank" rel="nofollow"}, we hide the complexity of deployment and delete coordination under `deploy`, `delete`, and `create_lambda_functions` methods. +Under [`BaseInfrastructure`](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/e2e/utils/infrastructure.py){target="_blank"}, we hide the complexity of deployment and delete coordination under `deploy`, `delete`, and `create_lambda_functions` methods. This allows us to benefit from test and deployment parallelization, use IDE step-through debugging for a single test, run one, subset, or all tests and only deploy their related infrastructure, without any custom configuration. @@ -590,7 +590,7 @@ graph TD #### CDK CLI parallelization -For CDK CLI to work with [independent CDK Apps](https://docs.aws.amazon.com/cdk/v2/guide/apps.html){target="_blank" rel="nofollow"}, we specify an output directory when synthesizing our stack and deploy from said output directory. +For CDK CLI to work with [independent CDK Apps](https://docs.aws.amazon.com/cdk/v2/guide/apps.html){target="_blank"}, we specify an output directory when synthesizing our stack and deploy from said output directory. ```mermaid flowchart TD @@ -658,6 +658,6 @@ Where: - **`layer_build`**. Contains our Lambda Layer source code built once, used by all stacks independently - **`layer_build.diff`**. Contains a hash on whether our source code has changed to speed up further deployments and E2E tests -Together, all of this allows us to use Pytest like we would for any project, use CDK CLI and its [context methods](https://docs.aws.amazon.com/cdk/v2/guide/context.html#context_methods){target="_blank" rel="nofollow"} (`from_lookup`), and use step-through debugging for a single E2E test without any extra configuration. +Together, all of this allows us to use Pytest like we would for any project, use CDK CLI and its [context methods](https://docs.aws.amazon.com/cdk/v2/guide/context.html#context_methods){target="_blank"} (`from_lookup`), and use step-through debugging for a single E2E test without any extra configuration. > NOTE: VSCode doesn't support debugging processes spawning sub-processes (like CDK CLI does w/ shell and CDK App). Maybe [this works](https://stackoverflow.com/a/65339352){target="_blank" rel="nofollow"}. PyCharm works just fine. diff --git a/docs/roadmap.md b/docs/roadmap.md index f432c2c56f7..6b4807f6ddc 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -4,13 +4,13 @@ This is our public roadmap that outlines the high level direction we are working towards, namely [Themes](#themes). We update this document when our priorities change: security and stability is our top priority. -[See our latest list of activities »](https://github.com/orgs/awslabs/projects/51/views/1?query=is%3Aopen+sort%3Aupdated-desc){target="_blank" rel="nofollow"} +[See our latest list of activities »](https://github.com/orgs/aws-powertools/projects/3?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"} ## Themes !!! info "Operational Excellence is priority number 1." -Themes are key activities maintainers are focusing on, besides bug reports. These are updated periodically and you can find the latest [under Epics in our public board](https://github.com/orgs/awslabs/projects/51/views/11?query=is%3Aopen+sort%3Aupdated-desc){target="_blank" rel="nofollow"}. +Themes are key activities maintainers are focusing on, besides bug reports. These are updated periodically and you can find the latest [under Epics in our public board](https://github.com/orgs/aws-powertools/projects/3/views/11?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"}. ### Increased end-to-end coverage @@ -20,7 +20,7 @@ Some Lambda Event Sources require clusters (e.g., MSK) leading to additional del ### Observability providers -We want to extend Tracer, Metrics, and Logger to support any [observability provider](https://github.com/aws-powertools/powertools-lambda-python/issues/1433){target="_blank" rel="nofollow"}. We need a RFC to define a contract and to identify two most requested observability providers that we can work with as an initial step. +We want to extend Tracer, Metrics, and Logger to support any [observability provider](https://github.com/aws-powertools/powertools-lambda-python/issues/1433){target="_blank"}. We need a RFC to define a contract and to identify two most requested observability providers that we can work with as an initial step. ### Lambda Layer in release notes @@ -38,7 +38,7 @@ This also means bringing `typing-extensions` as a runtime dependency to ensure c ### New utilities -With V2 launched, we want to resume working on new utilities, specifically but not limited to the most commonly asked: **(1)** [Sensitive Data Masking](https://github.com/aws-powertools/powertools-lambda-python/issues/1173){target="_blank" rel="nofollow"}, **(2)** [Integration/End-to-end Testing](https://github.com/aws-powertools/powertools-lambda-python/issues/1169){target="_blank" rel="nofollow"}, and **(3)** [Event Bridge](https://github.com/aws-powertools/powertools-lambda-python/issues/1168){target="_blank" rel="nofollow"}. +With V2 launched, we want to resume working on new utilities, specifically but not limited to the most commonly asked: **(1)** [Sensitive Data Masking](https://github.com/aws-powertools/powertools-lambda-python/issues/1173){target="_blank"}, **(2)** [Integration/End-to-end Testing](https://github.com/aws-powertools/powertools-lambda-python/issues/1169){target="_blank"}, and **(3)** [Event Bridge](https://github.com/aws-powertools/powertools-lambda-python/issues/1168){target="_blank"}. ### Open iteration planning @@ -54,7 +54,7 @@ graph LR Visual representation
-Within our [public board](https://github.com/orgs/awslabs/projects/51/views/1?query=is%3Aopen+sort%3Aupdated-desc){target="_blank" rel="nofollow"}, you'll see the following values in the `Status` column: +Within our [public board](https://github.com/orgs/aws-powertools/projects/3/views/1?query=is%3Aopen+sort%3Aupdated-desc){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. @@ -82,14 +82,14 @@ graph LR Our end-to-end mechanism follows four major steps: -* **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&template=feature_request.yml&title=Feature+request%3A+TITLE){target="_blank" rel="nofollow"} 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" rel="nofollow"}, customers reaction (👍), and use cases. -* **Request-for-comments (RFC)**. Design proposals use our [RFC issue template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE){target="_blank" rel="nofollow"} to describe its implementation, challenges, developer experience, dependencies, and alternative solutions. +* **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&template=feature_request.yml&title=Feature+request%3A+TITLE){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 issue template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE){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](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md){target="_blank" rel="nofollow"} document to understand how we triage issues and pull requests, labels and governance." +???+ info "See [Maintainers](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md){target="_blank"} document to understand how we triage issues and pull requests, labels and governance." ## Disclaimer diff --git a/docs/security.md b/docs/security.md index 4572f921573..e8900366f3b 100644 --- a/docs/security.md +++ b/docs/security.md @@ -79,7 +79,7 @@ You can do this manually or automated via a shell script. We maintain the latter 5. **Runs SLSA Verifier against attestation**, GitHub Source, and release binary 6. **Cleanup** by removing downloaded files to keep your current directory tidy - ??? info "Expand or [click here](https://github.com/heitorlessa/aws-lambda-powertools-python/blob/refactor/ci-seal/.github/actions/verify-provenance/verify_provenance.sh#L95){target="_blank" rel="nofollow"} to see the script source code" + ??? info "Expand or [click here](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/.github/actions/verify-provenance/verify_provenance.sh){target="_blank"} to see the script source code" ```bash title=".github/actions/verify-provenance/verify_provenance.sh" ---8<-- ".github/actions/verify-provenance/verify_provenance.sh" diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index 28021ea191a..ae4fd4a7181 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -9,8 +9,8 @@ This tutorial progressively introduces Powertools for AWS Lambda (Python) core u ## Requirements -* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html){target="_blank" rel="nofollow"} and [configured with your credentials](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-set-up-credentials.html){target="_blank" rel="nofollow"}. -* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html){target="_blank" rel="nofollow"} installed. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html){target="_blank"} and [configured with your credentials](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-set-up-credentials.html){target="_blank"}. +* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html){target="_blank"} installed. ## Getting started @@ -87,7 +87,7 @@ Our Lambda code consists of an entry point function named `lambda_handler`, and When API Gateway receives a HTTP GET request on `/hello` route, Lambda will call our `lambda_handler` function, subsequently calling the `hello` function. API Gateway will use this response to return the correct HTTP Status Code and payload back to the caller. ???+ warning - For simplicity, we do not set up authentication and authorization! You can find more information on how to implement it on [AWS SAM documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-controlling-access-to-apis.html){target="_blank" rel="nofollow"}. + For simplicity, we do not set up authentication and authorization! You can find more information on how to implement it on [AWS SAM documentation](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-controlling-access-to-apis.html){target="_blank"}. ### Run your code @@ -111,7 +111,7 @@ As a result, a local API endpoint will be exposed and you can invoke it using yo ``` ???+ info - To learn more about local testing, please visit the [AWS SAM CLI local testing](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html){target="_blank" rel="nofollow"} documentation. + To learn more about local testing, please visit the [AWS SAM CLI local testing](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-start-api.html){target="_blank"} documentation. #### Live test @@ -147,7 +147,7 @@ At the end of the deployment, you will find the API endpoint URL within `Outputs ``` ???+ Info - For more details on AWS SAM deployment mechanism, see [SAM Deploy reference docs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html){target="_blank" rel="nofollow"}. + For more details on AWS SAM deployment mechanism, see [SAM Deploy reference docs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html){target="_blank"}. ## Routing @@ -226,7 +226,7 @@ For this to work, we could create a new Lambda function to handle incoming reque We could group similar routes and intents, separate read and write operations resulting in fewer functions. It doesn't address the boilerplate routing code, but maybe it will be easier to add additional URLs. ???+ info "Info: You might be already asking yourself about mono vs micro-functions" - If you want a more detailed explanation of these two approaches, head over to the [trade-offs on each approach](../core/event_handler/api_gateway/#considerations){target="_blank" rel="nofollow"} later. + If you want a more detailed explanation of these two approaches, head over to the [trade-offs on each approach](../core/event_handler/api_gateway/#considerations){target="_blank"} later. A first attempt at the routing logic might look similar to the following code snippet. @@ -318,10 +318,10 @@ However, it forces us to understand the internal structure of the API Gateway re ### Simplifying with Event Handler -We can massively simplify cross-cutting concerns while keeping it lightweight by using [Event Handler](../core/event_handler/api_gateway.md){target="_blank" rel="nofollow"}. +We can massively simplify cross-cutting concerns while keeping it lightweight by using [Event Handler](../core/event_handler/api_gateway.md){target="_blank"}. ???+ tip - This is available for both [REST API (API Gateway, ALB)](../core/event_handler/api_gateway.md){target="_blank" rel="nofollow"} and [GraphQL API (AppSync)](../core/event_handler/appsync.md){target="_blank" rel="nofollow"}. + This is available for both [REST API (API Gateway, ALB)](../core/event_handler/api_gateway.md){target="_blank"} and [GraphQL API (AppSync)](../core/event_handler/appsync.md){target="_blank"}. Let's include Powertools for AWS Lambda (Python) as a dependency in `requirement.txt`, and use Event Handler to refactor our previous example. @@ -355,13 +355,13 @@ Let's include Powertools for AWS Lambda (Python) as a dependency in `requirement Use `sam build && sam local start-api` and try run it locally again. ???+ note - If you're coming from [Flask](https://flask.palletsprojects.com/en/2.0.x/){target="_blank" rel="nofollow"}, you will be familiar with this experience already. [Event Handler for API Gateway](../core/event_handler/api_gateway.md){target="_blank" rel="nofollow"} uses `APIGatewayRestResolver` to give a Flask-like experience while staying true to our tenet `Keep it lean`. + If you're coming from [Flask](https://flask.palletsprojects.com/en/2.0.x/){target="_blank" rel="nofollow"}, you will be familiar with this experience already. [Event Handler for API Gateway](../core/event_handler/api_gateway.md){target="_blank"} uses `APIGatewayRestResolver` to give a Flask-like experience while staying true to our tenet `Keep it lean`. We have added the route annotation as the decorator for our methods. It enables us to use the parameters passed in the request directly, and our responses are simply dictionaries. Lastly, we used `return app.resolve(event, context)` so Event Handler can resolve routes, inject the current request, handle serialization, route validation, etc. -From here, we could handle [404 routes](../core/event_handler/api_gateway.md#handling-not-found-routes){target="_blank" rel="nofollow"}, [error handling](../core/event_handler/api_gateway.md#exception-handling){target="_blank" rel="nofollow"}, [access query strings, payload](../core/event_handler/api_gateway.md#accessing-request-details){target="_blank" rel="nofollow"}, etc. +From here, we could handle [404 routes](../core/event_handler/api_gateway.md#handling-not-found-routes){target="_blank"}, [error handling](../core/event_handler/api_gateway.md#exception-handling){target="_blank"}, [access query strings, payload](../core/event_handler/api_gateway.md#accessing-request-details){target="_blank"}, etc. ???+ tip If you'd like to learn how python decorators work under the hood, you can follow [Real Python](https://realpython.com/primer-on-python-decorators/){target="_blank" rel="nofollow"}'s article. @@ -370,7 +370,7 @@ From here, we could handle [404 routes](../core/event_handler/api_gateway.md#han Over time, you realize that searching logs as text results in poor observability, it's hard to create metrics from, enumerate common exceptions, etc. -Then, you decided to propose production quality logging capabilities to your Lambda code. You found out that by having logs as `JSON` you can [structure them](https://docs.aws.amazon.com/lambda/latest/operatorguide/parse-logs.html){target="_blank" rel="nofollow"}, so that you can use any Log Analytics tool out there to quickly analyze them. +Then, you decided to propose production quality logging capabilities to your Lambda code. You found out that by having logs as `JSON` you can [structure them](https://docs.aws.amazon.com/lambda/latest/operatorguide/parse-logs.html){target="_blank"}, so that you can use any Log Analytics tool out there to quickly analyze them. This helps not only in searching, but produces consistent logs containing enough context and data to ask arbitrary questions on the status of your system. We can take advantage of CloudWatch Logs and Cloudwatch Insight for this purpose. @@ -454,7 +454,7 @@ We could start by creating a dictionary with Lambda context information or somet ???+ question "Surely this could be easier, right?" Yes! Powertools for AWS Lambda (Python) Logger to the rescue :-) -As we already have Powertools for AWS Lambda (Python) as a dependency, we can simply import [Logger](../core/logger.md){target="_blank" rel="nofollow"}. +As we already have Powertools for AWS Lambda (Python) as a dependency, we can simply import [Logger](../core/logger.md){target="_blank"}. ```python title="Refactoring with Powertools for AWS Lambda (Python) Logger" hl_lines="1 3 5 12 18 22" from aws_lambda_powertools import Logger @@ -487,8 +487,8 @@ Let's break this down: * **L5**: We add Powertools for AWS Lambda (Python) Logger; the boilerplate is now done for you. By default, we set `INFO` as the logging level if `LOG_LEVEL` env var isn't set. * **L22**: We use `logger.inject_lambda_context` decorator to inject key information from Lambda context into every log. -* **L22**: We also instruct Logger to use the incoming API Gateway Request ID as a [correlation id](../core/logger.md##set_correlation_id-method){target="_blank" rel="nofollow"} automatically. -* **L22**: Since we're in dev, we also use `log_event=True` to automatically log each incoming request for debugging. This can be also set via [environment variables](./index.md#environment-variables){target="_blank" rel="nofollow"}. +* **L22**: We also instruct Logger to use the incoming API Gateway Request ID as a [correlation id](../core/logger.md##set_correlation_id-method){target="_blank"} automatically. +* **L22**: Since we're in dev, we also use `log_event=True` to automatically log each incoming request for debugging. This can be also set via [environment variables](./index.md#environment-variables){target="_blank"}. This is how the logs would look like now: @@ -510,9 +510,9 @@ This is how the logs would look like now: We can now search our logs by the request ID to find a specific operation. Additionally, we can also search our logs for function name, Lambda request ID, Lambda function ARN, find out whether an operation was a cold start, etc. -From here, we could [set specific keys](../core/logger.md#append_keys-method){target="_blank" rel="nofollow"} to add additional contextual information about a given operation, [log exceptions](../core/logger.md#logging-exceptions){target="_blank" rel="nofollow"} to easily enumerate them later, [sample debug logs](../core/logger.md#sampling-debug-logs){target="_blank" rel="nofollow"}, etc. +From here, we could [set specific keys](../core/logger.md#append_keys-method){target="_blank"} to add additional contextual information about a given operation, [log exceptions](../core/logger.md#logging-exceptions){target="_blank"} to easily enumerate them later, [sample debug logs](../core/logger.md#sampling-debug-logs){target="_blank"}, etc. -By having structured logs like this, we can easily search and analyse them in [CloudWatch Logs Insight](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html){target="_blank" rel="nofollow"}. +By having structured logs like this, we can easily search and analyse them in [CloudWatch Logs Insight](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html){target="_blank"}. === "CloudWatch Logs Insight Example" ![CloudWatch Logs Insight Example](../media/cloudwatch_logs_insight_example.png) @@ -528,14 +528,14 @@ Combined with structured logs, it is an important step to be able to observe how ### Generating traces -[AWS X-Ray](https://aws.amazon.com/xray/){target="_blank" rel="nofollow"} is the distributed tracing service we're going to use. But how do we generate application traces in the first place? +[AWS X-Ray](https://aws.amazon.com/xray/){target="_blank"} is the distributed tracing service we're going to use. But how do we generate application traces in the first place? -It's a [two-step process](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank" rel="nofollow"}: +It's a [two-step process](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"}: 1. Enable tracing in your Lambda function. 2. Instrument your application code. -Let's explore how we can instrument our code with [AWS X-Ray SDK](https://docs.aws.amazon.com/xray-sdk-for-python/latest/reference/index.html){target="_blank" rel="nofollow"}, and then simplify it with [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank" rel="nofollow"} feature. +Let's explore how we can instrument our code with [AWS X-Ray SDK](https://docs.aws.amazon.com/xray-sdk-for-python/latest/reference/index.html){target="_blank"}, and then simplify it with [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank"} feature. === "app.py" @@ -616,7 +616,7 @@ Let's explore how we can instrument our code with [AWS X-Ray SDK](https://docs.a Let's break it down: -* **L1**: First, we import AWS X-Ray SDK. `xray_recorder` records blocks of code being traced ([subsegment](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-subsegments){target="_blank" rel="nofollow"}). It also sends generated traces to the AWS X-Ray daemon running in the Lambda service who subsequently forwards them to AWS X-Ray service. +* **L1**: First, we import AWS X-Ray SDK. `xray_recorder` records blocks of code being traced ([subsegment](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-subsegments){target="_blank"}). It also sends generated traces to the AWS X-Ray daemon running in the Lambda service who subsequently forwards them to AWS X-Ray service. * **L13,20,27**: We decorate our function so the SDK traces the end-to-end execution, and the argument names the generated block being traced. ???+ question @@ -625,9 +625,9 @@ Let's break it down: We've made the following changes in `template.yaml` for this to work seamless: * **L7-8**: Enables tracing for Amazon API Gateway. -* **L16**: Enables tracing for our Serverless Function. This will also add a managed IAM Policy named [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess){target="_blank" rel="nofollow"} to allow Lambda to send traces to AWS X-Ray. +* **L16**: Enables tracing for our Serverless Function. This will also add a managed IAM Policy named [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess){target="_blank"} to allow Lambda to send traces to AWS X-Ray. -You can now build and deploy our updates with `sam build && sam deploy`. Once deployed, try invoking the application via the API endpoint, and visit [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank" rel="nofollow"} to see how much progress we've made so far!! +You can now build and deploy our updates with `sam build && sam deploy`. Once deployed, try invoking the application via the API endpoint, and visit [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"} to see how much progress we've made so far!! ![AWS X-Ray Console trace view](../media/tracer_xray_sdk_showcase.png) @@ -644,7 +644,7 @@ What we've done helps bring an initial visibility, but we can do so much more. Within AWS X-Ray, we can answer these questions by using two features: tracing **Annotations** and **Metadata**. -**Annotations** are simple key-value pairs that are indexed for use with [filter expressions](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html){target="_blank" rel="nofollow"}. +**Annotations** are simple key-value pairs that are indexed for use with [filter expressions](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-filters.html){target="_blank"}. **Metadata** are key-value pairs with values of any type, including objects and lists, but that are not indexed. Let's put them into action. @@ -708,11 +708,11 @@ Let's break it down: * **L44**: We include the final response under `response` key as part of the `handler` subsegment. ???+ info - If you want to understand how the Lambda execution environment (sandbox) works and why cold starts can occur, see this [blog series on Lambda performance](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/){target="_blank" rel="nofollow"}. + If you want to understand how the Lambda execution environment (sandbox) works and why cold starts can occur, see this [blog series on Lambda performance](https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/){target="_blank"}. Repeat the process of building, deploying, and invoking your application via the API endpoint. -Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank" rel="nofollow"}, you should now be able to group traces by the `User` and `ColdStart` annotation. +Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"}, you should now be able to group traces by the `User` and `ColdStart` annotation. ![Filtering traces by annotations](../media/tracer_xray_sdk_enriched.png) @@ -724,7 +724,7 @@ If you choose any of the traces available, try opening the `handler` subsegment Cross-cutting concerns like filtering traces by Cold Start, including response as well as exceptions as tracing metadata can take a considerable amount of boilerplate. -We can simplify our previous patterns by using [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank" rel="nofollow"}; a thin wrapper on top of X-Ray SDK. +We can simplify our previous patterns by using [Powertools for AWS Lambda (Python) Tracer](../core/tracer.md){target="_blank"}; a thin wrapper on top of X-Ray SDK. ???+ note You can now safely remove `aws-xray-sdk` from `requirements.txt`; keep `aws-lambda-powertools` only. @@ -773,21 +773,21 @@ Another subtle difference is that you can now run your Lambda functions and unit Powertools for AWS Lambda (Python) optimizes for Lambda compute environment. As such, we add these and other common approaches to accelerate your development, so you don't worry about implementing every cross-cutting concern. ???+ tip - You can [opt-out some of these behaviours](../core/tracer/#advanced){target="_blank" rel="nofollow"} like disabling response capturing, explicitly patching only X modules, etc. + You can [opt-out some of these behaviours](../core/tracer/#advanced){target="_blank"} like disabling response capturing, explicitly patching only X modules, etc. -Repeat the process of building, deploying, and invoking your application via the API endpoint. Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank" rel="nofollow"}, you should see a similar view: +Repeat the process of building, deploying, and invoking your application via the API endpoint. Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"}, you should see a similar view: ![AWS X-Ray Console trace view using Powertools for AWS Lambda (Python) Tracer](../media/tracer_utility_showcase_2.png) ???+ tip - Consider using [Amazon CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank" rel="nofollow"} as it aggregates AWS X-Ray traces and CloudWatch metrics and logs in one view. + Consider using [Amazon CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank"} as it aggregates AWS X-Ray traces and CloudWatch metrics and logs in one view. From here, you can browse to specific logs in CloudWatch Logs Insight, Metrics Dashboard or AWS X-Ray traces. ![CloudWatch ServiceLens View](../media/tracer_utility_showcase_3.png) ???+ info - For more information on Amazon CloudWatch ServiceLens, please visit [link](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceLens.html){target="_blank" rel="nofollow"}. + For more information on Amazon CloudWatch ServiceLens, please visit [link](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ServiceLens.html){target="_blank"}. ## Custom Metrics @@ -795,10 +795,10 @@ From here, you can browse to specific logs in CloudWatch Logs Insight, Metrics D Let's add custom metrics to better understand our application and business behavior (e.g. number of reservations, etc.). -By default, AWS Lambda adds [invocation and performance metrics](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-types){target="_blank" rel="nofollow"}, and Amazon API Gateway adds [latency and some HTTP metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metrics){target="_blank" rel="nofollow"}. +By default, AWS Lambda adds [invocation and performance metrics](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics.html#monitoring-metrics-types){target="_blank"}, and Amazon API Gateway adds [latency and some HTTP metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metrics){target="_blank"}. ???+ tip - You can [optionally enable detailed metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metricdimensions){target="_blank" rel="nofollow"} per each API route, stage, and method in API Gateway. + You can [optionally enable detailed metrics](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html#api-gateway-metricdimensions){target="_blank"} per each API route, stage, and method in API Gateway. Let's expand our application with custom metrics using AWS SDK to see how it works, then let's upgrade it with Powertools for AWS Lambda (Python) :-) @@ -917,16 +917,16 @@ Let's expand our application with custom metrics using AWS SDK to see how it wor There's a lot going on, let's break this down: -* **L10**: We define a container where all of our application metrics will live `MyApp`, a.k.a [Metrics Namespace](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html){target="_blank" rel="nofollow"}. +* **L10**: We define a container where all of our application metrics will live `MyApp`, a.k.a [Metrics Namespace](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html){target="_blank"}. * **L14**: We initialize a CloudWatch client to send metrics later. -* **L19-47**: We create a custom function to prepare and send `ColdStart` and `SuccessfulGreetings` metrics using CloudWatch expected data structure. We also set [dimensions](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Dimension){target="_blank" rel="nofollow"} of these metrics. +* **L19-47**: We create a custom function to prepare and send `ColdStart` and `SuccessfulGreetings` metrics using CloudWatch expected data structure. We also set [dimensions](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Dimension){target="_blank"} of these metrics. * Think of them as metadata to define to slice and dice them later; an unique metric is a combination of metric name + metric dimension(s). * **L55,64**: We call our custom function to create metrics for every greeting received. ???+ question But what permissions do I need to send metrics to CloudWatch? -Within `template.yaml`, we add [CloudWatchPutMetricPolicy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-template-list.html#cloudwatch-put-metric-policy){target="_blank" rel="nofollow"} policy in SAM. +Within `template.yaml`, we add [CloudWatchPutMetricPolicy](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-template-list.html#cloudwatch-put-metric-policy){target="_blank"} policy in SAM. ???+ note "Adding metrics via AWS SDK gives a lot of flexibility at a cost" `put_metric_data` is a synchronous call to CloudWatch Metrics API. This means establishing a connection to CloudWatch endpoint, sending metrics payload, and waiting from a response. @@ -935,12 +935,12 @@ Within `template.yaml`, we add [CloudWatchPutMetricPolicy](https://docs.aws.amaz ### Simplifying with Metrics -[Powertools for AWS Lambda (Python) Metrics](../core/metrics.md){target="_blank} uses [Amazon CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html){target="_blank" rel="nofollow"} to create custom metrics **asynchronously** via a native integration with Lambda. +[Powertools for AWS Lambda (Python) Metrics](../core/metrics.md){target="_blank} uses [Amazon CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html){target="_blank"} to create custom metrics **asynchronously** via a native integration with Lambda. In general terms, EMF is a specification that expects metrics in a JSON payload within CloudWatch Logs. Lambda ingests all logs emitted by a given function into CloudWatch Logs. CloudWatch automatically looks up for log entries that follow the EMF format and transforms them into a CloudWatch metric. ???+ info - If you are interested in the details of the EMF mechanism, follow [blog post](https://aws.amazon.com/blogs/mt/enhancing-workload-observability-using-amazon-cloudwatch-embedded-metric-format/){target="_blank" rel="nofollow"}. + If you are interested in the details of the EMF mechanism, follow [blog post](https://aws.amazon.com/blogs/mt/enhancing-workload-observability-using-amazon-cloudwatch-embedded-metric-format/){target="_blank"}. Let's implement that using [Metrics](../core/metrics.md){target="_blank}: @@ -991,7 +991,7 @@ That's a lot less boilerplate code! Let's break this down: * **L9**: We initialize `Metrics` with our service name (`APP`) and metrics namespace (`MyApp`), reducing the need to add the `service` dimension for every metric and setting the namespace later * **L18, 27**: We use `add_metric` similarly to our custom function, except we now have an enum `MetricCount` to help us understand which Metric Units we have at our disposal * **L33**: We use `@metrics.log_metrics` decorator to ensure that our metrics are aligned with the EMF output and validated before-hand, like in case we forget to set namespace, or accidentally use a metric unit as a string that doesn't exist in CloudWatch. -* **L33**: We also use `capture_cold_start_metric=True` so we don't have to handle that logic either. Note that [Metrics](../core/metrics.md){target="_blank" rel="nofollow"} does not publish a warm invocation metric (ColdStart=0) for cost reasons. As such, treat the absence (sparse metric) as a non-cold start invocation. +* **L33**: We also use `capture_cold_start_metric=True` so we don't have to handle that logic either. Note that [Metrics](../core/metrics.md){target="_blank"} does not publish a warm invocation metric (ColdStart=0) for cost reasons. As such, treat the absence (sparse metric) as a non-cold start invocation. Repeat the process of building, deploying, and invoking your application via the API endpoint a few times to generate metrics - [Artillery](https://www.artillery.io/){target="_blank" rel="nofollow"} and [K6.io](https://k6.io/open-source){target="_blank" rel="nofollow"} are quick ways to generate some load. @@ -999,7 +999,7 @@ Within [CloudWatch Metrics view](https://console.aws.amazon.com/cloudwatch/home# ![Custom Metrics Example](../media/metrics_utility_showcase.png) -If you're curious about how the EMF portion of your function logs look like, you can quickly go to [CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank" rel="nofollow"}, choose your function and open logs. You will see a similar entry that looks like this: +If you're curious about how the EMF portion of your function logs look like, you can quickly go to [CloudWatch ServiceLens view](https://console.aws.amazon.com/cloudwatch/home#servicelens:service-map/map){target="_blank"}, choose your function and open logs. You will see a similar entry that looks like this: ```json { @@ -1035,14 +1035,14 @@ If you're curious about how the EMF portion of your function logs look like, you We covered a lot of ground here and we only scratched the surface of the feature set available within Powertools for AWS Lambda (Python). -When it comes to the observability features ([Tracer](../core/tracer.md){target="_blank" rel="nofollow"}, [Metrics](../core/metrics.md){target="_blank" rel="nofollow"}, [Logging](../core/logger.md){target="_blank" rel="nofollow"}), don't stop there! The goal here is to ensure you can ask arbitrary questions to assess your system's health; these features are only part of the wider story! +When it comes to the observability features ([Tracer](../core/tracer.md){target="_blank"}, [Metrics](../core/metrics.md){target="_blank"}, [Logging](../core/logger.md){target="_blank"}), don't stop there! The goal here is to ensure you can ask arbitrary questions to assess your system's health; these features are only part of the wider story! This requires a change in mindset to ensure operational excellence is part of the software development lifecycle. ???+ tip - You can find more details on other leading practices described in the [Well-Architected Serverless Lens](https://aws.amazon.com/blogs/aws/new-serverless-lens-in-aws-well-architected-tool/){target="_blank" rel="nofollow"}. + You can find more details on other leading practices described in the [Well-Architected Serverless Lens](https://aws.amazon.com/blogs/aws/new-serverless-lens-in-aws-well-architected-tool/){target="_blank"}. Powertools for AWS Lambda (Python) is largely designed to make some of these practices easier to adopt from day 1. ???+ question "Have ideas for other tutorials?" - You can open up a [documentation issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=documentation&template=documentation-improvements.md&title=Tutorial%20Suggestion){target="_blank" rel="nofollow"}, or via e-mail [aws-lambda-powertools-feedback@amazon.com](mailto:aws-lambda-powertools-feedback@amazon.com). + You can open up a [documentation issue](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=documentation&template=documentation-improvements.md&title=Tutorial%20Suggestion){target="_blank"}, or via e-mail [aws-lambda-powertools-feedback@amazon.com](mailto:aws-lambda-powertools-feedback@amazon.com). diff --git a/docs/upgrade.md b/docs/upgrade.md index 509bffda15c..064c6a9657a 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -9,7 +9,7 @@ description: Guide to update between major Powertools for AWS Lambda (Python) ve !!! warning "On March 31st, 2023, Powertools for AWS Lambda (Python) v1 reached 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 (Python), we will keep [Pypi](https://pypi.org/project/aws-lambda-powertools/){target="_blank" rel="nofollow"} v1 releases and documentation 1.x versions to prevent any disruption. +Given our commitment to all of our customers using Powertools for AWS Lambda (Python), we will keep [Pypi](https://pypi.org/project/aws-lambda-powertools/){target="_blank"} v1 releases and documentation 1.x versions to prevent any disruption. ## Migrate to v2 from v1 @@ -20,20 +20,20 @@ We've made minimal breaking changes to make your transition to v2 as smooth as p | Area | Change | Code change required | IAM Permissions change required | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------------- | | **Batch** | Removed legacy [SQS batch processor](#legacy-sqs-batch-processor) in favour of **`BatchProcessor`**. | Yes | - | -| **Environment variables** | Removed legacy **`POWERTOOLS_EVENT_HANDLER_DEBUG`** in favour of [`POWERTOOLS_DEV`](index.md#optimizing-for-non-production-environments){target="_blank" rel="nofollow"}. | - | - | -| **Event Handler** | Updated [headers response format](#event-handler-headers-response-format) due to [multi-value headers and cookie support](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank" rel="nofollow"}. | Tests only | - | +| **Environment variables** | Removed legacy **`POWERTOOLS_EVENT_HANDLER_DEBUG`** in favour of [`POWERTOOLS_DEV`](index.md#optimizing-for-non-production-environments){target="_blank"}. | - | - | +| **Event Handler** | Updated [headers response format](#event-handler-headers-response-format) due to [multi-value headers and cookie support](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank"}. | Tests only | - | | **Event Source Data Classes** | Replaced [DynamoDBStreamEvent](#dynamodbstreamevent-in-event-source-data-classes) `AttributeValue` with native Python types. | Yes | - | | **Feature Flags** / **Parameters** | Updated [AppConfig API calls](#feature-flags-and-appconfig-parameter-utility) due to **`GetConfiguration`** API deprecation. | - | Yes | | **Idempotency** | Updated [partition key](#idempotency-partition-key-format) to include fully qualified function/method names. | - | - | ### First Steps -!!! note "All dependencies are optional now. [Tracer](core/tracer.md#install){target="_blank" rel="nofollow"}, [Validation](./utilities/validation.md#install){target="_blank" rel="nofollow"}, and [Parser](./utilities/parser.md){target="_blank" rel="nofollow"} now require additional dependencies." +!!! note "All dependencies are optional now. [Tracer](core/tracer.md#install){target="_blank"}, [Validation](./utilities/validation.md#install){target="_blank"}, and [Parser](./utilities/parser.md){target="_blank"} now require additional dependencies." Before you start, we suggest making a copy of your current working project or create a new branch with git. 1. **Upgrade** Python to at least v3.7 -2. **Ensure** you have the latest version via [Lambda Layer or PyPi](index.md#install){target="_blank" rel="nofollow"}. +2. **Ensure** you have the latest version via [Lambda Layer or PyPi](index.md#install){target="_blank"}. 3. **Review** the following sections to confirm whether they affect your code ## Legacy SQS Batch Processor @@ -44,7 +44,7 @@ You can migrate to `BatchProcessor` with the following changes: 1. If you use **`sqs_batch_decorator`**, change to **`batch_processor`** decorator 2. If you use **`PartialSQSProcessor`**, change to **`BatchProcessor`** -3. [Enable **`ReportBatchItemFailures`** in your Lambda Event Source](../utilities/batch#required-resources){target="_blank" rel="nofollow"} +3. [Enable **`ReportBatchItemFailures`** in your Lambda Event Source](../utilities/batch#required-resources){target="_blank"} 4. Change your Lambda Handler to return the new response format === "[Before] Decorator" @@ -139,7 +139,7 @@ Previously, custom headers were available under `headers` key in the Event Handl } ``` -In V2, we add all headers under `multiValueHeaders` key. This enables seamless support for multi-value headers and cookies in [fine grained responses](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank" rel="nofollow"}. +In V2, we add all headers under `multiValueHeaders` key. This enables seamless support for multi-value headers and cookies in [fine grained responses](./core/event_handler/api_gateway.md#fine-grained-responses){target="_blank"}. ```python title="V2 response headers" hl_lines="2" { @@ -151,7 +151,7 @@ In V2, we add all headers under `multiValueHeaders` key. This enables seamless s ## DynamoDBStreamEvent in Event Source Data Classes -!!! info "This also applies if you're using [**DynamoDB BatchProcessor**](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-dynamodb){target="_blank" rel="nofollow"}." +!!! info "This also applies if you're using [**DynamoDB BatchProcessor**](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/#processing-messages-from-dynamodb){target="_blank"}." You will now receive native Python types when accessing DynamoDB records via `keys`, `new_image`, and `old_image` attributes in `DynamoDBStreamEvent`. @@ -196,7 +196,7 @@ def lambda_handler(event: DynamoDBStreamEvent, context): !!! note "No code changes required" -We replaced `GetConfiguration` API ([now deprecated](https://github.com/aws-powertools/powertools-lambda-python/issues/1506#issuecomment-1266645884){target="_blank" rel="nofollow"}) with `GetLatestConfiguration` and `StartConfigurationSession`. +We replaced `GetConfiguration` API ([now deprecated](https://github.com/aws-powertools/powertools-lambda-python/issues/1506#issuecomment-1266645884){target="_blank"}) with `GetLatestConfiguration` and `StartConfigurationSession`. As such, you must update your IAM Role permissions to allow the following IAM actions: @@ -217,7 +217,7 @@ Previously, we used the function/method name to generate the partition key value In V2, we now distinguish between distinct classes or modules that may have the same function/method name. -[For example](https://github.com/aws-powertools/powertools-lambda-python/issues/1330){target="_blank" rel="nofollow"}, an ABC or Protocol class may have multiple implementations of `process_payment` method and may have different results. +[For example](https://github.com/aws-powertools/powertools-lambda-python/issues/1330){target="_blank"}, an ABC or Protocol class may have multiple implementations of `process_payment` method and may have different results. diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 57e0a6020b1..0ef0a1366cb 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -59,9 +59,9 @@ This behavior changes when you enable Report Batch Item Failures feature in your ???+ warning "Warning: This utility lowers the chance of processing records more than once; it does not guarantee it" - We recommend implementing processing logic in an [idempotent manner](idempotency.md){target="_blank" rel="nofollow"} wherever possible. + We recommend implementing processing logic in an [idempotent manner](idempotency.md){target="_blank"} wherever possible. - You can find more details on how Lambda works with either [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html){target="_blank" rel="nofollow"}, [Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html){target="_blank" rel="nofollow"}, or [DynamoDB](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html){target="_blank" rel="nofollow"} in the AWS Documentation. + You can find more details on how Lambda works with either [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html){target="_blank"}, [Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html){target="_blank"}, or [DynamoDB](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html){target="_blank"} in the AWS Documentation. ## Getting started @@ -98,7 +98,7 @@ The remaining sections of the documentation will rely on these samples. For comp Processing batches from SQS works in three stages: 1. Instantiate **`BatchProcessor`** and choose **`EventType.SQS`** for the event type -2. Define your function to handle each batch record, and use [`SQSRecord`](data_classes.md#sqs){target="_blank" rel="nofollow"} type annotation for autocompletion +2. Define your function to handle each batch record, and use [`SQSRecord`](data_classes.md#sqs){target="_blank"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing !!! info "This code example uses Tracer and Logger for completion." @@ -169,7 +169,7 @@ This helps preserve the ordering of messages in your queue. Processing batches from Kinesis works in three stages: 1. Instantiate **`BatchProcessor`** and choose **`EventType.KinesisDataStreams`** for the event type -2. Define your function to handle each batch record, and use [`KinesisStreamRecord`](data_classes.md#kinesis-streams){target="_blank" rel="nofollow"} type annotation for autocompletion +2. Define your function to handle each batch record, and use [`KinesisStreamRecord`](data_classes.md#kinesis-streams){target="_blank"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing !!! info "This code example uses Tracer and Logger for completion." @@ -213,7 +213,7 @@ Processing batches from Kinesis works in three stages: Processing batches from DynamoDB Streams works in three stages: 1. Instantiate **`BatchProcessor`** and choose **`EventType.DynamoDBStreams`** for the event type -2. Define your function to handle each batch record, and use [`DynamoDBRecord`](data_classes.md#dynamodb-streams){target="_blank" rel="nofollow"} type annotation for autocompletion +2. Define your function to handle each batch record, and use [`DynamoDBRecord`](data_classes.md#dynamodb-streams){target="_blank"} type annotation for autocompletion 3. Use **`process_partial_response`** to kick off processing !!! info "This code example uses Tracer and Logger for completion." @@ -578,7 +578,7 @@ You can then use this class as a context manager, or pass it to `batch_processor When using Tracer to capture responses for each batch record processing, you might exceed 64K of tracing data depending on what you return from your `record_handler` function, or how big is your batch size. -If that's the case, you can configure [Tracer to disable response auto-capturing](../core/tracer.md#disabling-response-auto-capture){target="_blank" rel="nofollow"}. +If that's the case, you can configure [Tracer to disable response auto-capturing](../core/tracer.md#disabling-response-auto-capture){target="_blank"}. ```python hl_lines="17" title="Disabling Tracer response auto-capturing" --8<-- "examples/batch_processing/src/disable_tracing.py" @@ -626,7 +626,7 @@ As 2.12.0, `process_partial_response` and `async_process_partial_response` are t When using Sentry.io for error monitoring, you can override `failure_handler` to capture each processing exception with Sentry SDK: -> Credits to [Charles-Axel Dein](https://github.com/aws-powertools/powertools-lambda-python/issues/293#issuecomment-781961732){target="_blank" rel="nofollow"} +> Credits to [Charles-Axel Dein](https://github.com/aws-powertools/powertools-lambda-python/issues/293#issuecomment-781961732){target="_blank"} ```python hl_lines="1 7-8" title="Integrating error tracking with Sentry.io" --8<-- "examples/batch_processing/src/sentry_error_tracking.py" diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index ca41dbe01ea..7b3aa74e275 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -111,8 +111,8 @@ Log Data Event for Troubleshooting ### Active MQ -It is used for [Active MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank" rel="nofollow"}, also see -the [AWS blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-as-an-event-source-for-aws-lambda/){target="_blank" rel="nofollow"} +It is used for [Active MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank"}, also see +the [AWS blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-as-an-event-source-for-aws-lambda/){target="_blank"} for more details. === "app.py" @@ -138,7 +138,7 @@ for more details. > New in 1.20.0 -It is used for [API Gateway Rest API Lambda Authorizer payload](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html){target="_blank" rel="nofollow"}. +It is used for [API Gateway Rest API Lambda Authorizer payload](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html){target="_blank"}. Use **`APIGatewayAuthorizerRequestEvent`** for type `REQUEST` and **`APIGatewayAuthorizerTokenEvent`** for type `TOKEN`. @@ -234,8 +234,8 @@ Use **`APIGatewayAuthorizerRequestEvent`** for type `REQUEST` and **`APIGatewayA > New in 1.20.0 -It is used for [API Gateway HTTP API Lambda Authorizer payload version 2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html){target="_blank" rel="nofollow"}. -See also [this blog post](https://aws.amazon.com/blogs/compute/introducing-iam-and-lambda-authorizers-for-amazon-api-gateway-http-apis/){target="_blank" rel="nofollow"} for more details. +It is used for [API Gateway HTTP API Lambda Authorizer payload version 2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html){target="_blank"}. +See also [this blog post](https://aws.amazon.com/blogs/compute/introducing-iam-and-lambda-authorizers-for-amazon-api-gateway-http-apis/){target="_blank"} for more details. === "app.py" @@ -320,9 +320,9 @@ Is it used for Application load balancer event. > New in 1.20.0 -Used when building an [AWS_LAMBDA Authorization](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-lambda-authorization){target="_blank" rel="nofollow"} with AppSync. -See blog post [Introducing Lambda authorization for AWS AppSync GraphQL APIs](https://aws.amazon.com/blogs/mobile/appsync-lambda-auth/){target="_blank" rel="nofollow"} -or read the Amplify documentation on using [AWS Lambda for authorization](https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js#aws-lambda){target="_blank" rel="nofollow"} with AppSync. +Used when building an [AWS_LAMBDA Authorization](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#aws-lambda-authorization){target="_blank"} with AppSync. +See blog post [Introducing Lambda authorization for AWS AppSync GraphQL APIs](https://aws.amazon.com/blogs/mobile/appsync-lambda-auth/){target="_blank"} +or read the Amplify documentation on using [AWS Lambda for authorization](https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js#aws-lambda){target="_blank"} with AppSync. In this example extract the `requestId` as the `correlation_id` for logging, used `@event_source` decorator and builds the AppSync authorizer using the `AppSyncAuthorizerResponse` helper. @@ -368,8 +368,8 @@ In this example extract the `requestId` as the `correlation_id` for logging, use > New in 1.12.0 -Used when building Lambda GraphQL Resolvers with [Amplify GraphQL Transform Library](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank" rel="nofollow"} (`@function`), -and [AppSync Direct Lambda Resolvers](https://aws.amazon.com/blogs/mobile/appsync-direct-lambda/){target="_blank" rel="nofollow"}. +Used when building Lambda GraphQL Resolvers with [Amplify GraphQL Transform Library](https://docs.amplify.aws/cli/graphql-transformer/function){target="_blank"} (`@function`), +and [AppSync Direct Lambda Resolvers](https://aws.amazon.com/blogs/mobile/appsync-direct-lambda/){target="_blank"}. In this example, we also use the new Logger `correlation_id` and built-in `correlation_paths` to extract, if available, X-Ray Trace ID in AppSync request headers: @@ -538,7 +538,7 @@ decompress and parse json data from the event. #### Kinesis integration -[When streaming CloudWatch Logs to a Kinesis Data Stream](https://aws.amazon.com/premiumsupport/knowledge-center/streaming-cloudwatch-logs/){target="_blank" rel="nofollow"} (cross-account or not), you can use `extract_cloudwatch_logs_from_event` to decode, decompress and extract logs as `CloudWatchLogsDecodedData` to ease log processing. +[When streaming CloudWatch Logs to a Kinesis Data Stream](https://aws.amazon.com/premiumsupport/knowledge-center/streaming-cloudwatch-logs/){target="_blank"} (cross-account or not), you can use `extract_cloudwatch_logs_from_event` to decode, decompress and extract logs as `CloudWatchLogsDecodedData` to ease log processing. === "app.py" @@ -560,7 +560,7 @@ decompress and parse json data from the event. return "nothing to be processed" ``` -Alternatively, you can use `extract_cloudwatch_logs_from_record` to seamless integrate with the [Batch utility](./batch.md){target="_blank" rel="nofollow"} for more robust log processing. +Alternatively, you can use `extract_cloudwatch_logs_from_record` to seamless integrate with the [Batch utility](./batch.md){target="_blank"} for more robust log processing. === "app.py" @@ -636,7 +636,7 @@ Data classes and utility functions to help create continuous delivery pipelines ### Cognito User Pool -Cognito User Pools have several [different Lambda trigger sources](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-identity-pools-working-with-aws-lambda-trigger-sources){target="_blank" rel="nofollow"}, all of which map to a different data class, which +Cognito User Pools have several [different Lambda trigger sources](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-identity-pools-working-with-aws-lambda-trigger-sources){target="_blank"}, all of which map to a different data class, which can be imported from `aws_lambda_powertools.data_classes.cognito_user_pool_event`: | Trigger/Event Source | Data Class | @@ -671,7 +671,7 @@ can be imported from `aws_lambda_powertools.data_classes.cognito_user_pool_event ???+ note In this example we are modifying the wrapped dict response fields, so we need to return the json serializable wrapped event in `event.raw_event`. -This example is based on the AWS Cognito docs for [Define Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-define-auth-challenge.html){target="_blank" rel="nofollow"}. +This example is based on the AWS Cognito docs for [Define Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-define-auth-challenge.html){target="_blank"}. === "app.py" @@ -825,7 +825,7 @@ This example is based on the AWS Cognito docs for [Define Auth Challenge Lambda #### Create Auth Challenge Example -This example is based on the AWS Cognito docs for [Create Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-create-auth-challenge.html){target="_blank" rel="nofollow"}. +This example is based on the AWS Cognito docs for [Create Auth Challenge Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-create-auth-challenge.html){target="_blank"}. === "app.py" @@ -844,7 +844,7 @@ This example is based on the AWS Cognito docs for [Create Auth Challenge Lambda #### Verify Auth Challenge Response Example -This example is based on the AWS Cognito docs for [Verify Auth Challenge Response Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-verify-auth-challenge-response.html){target="_blank" rel="nofollow"}. +This example is based on the AWS Cognito docs for [Verify Auth Challenge Response Lambda Trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-verify-auth-challenge-response.html){target="_blank"}. === "app.py" @@ -936,7 +936,7 @@ The class automatically deserializes DynamoDB types into their equivalent Python ### Kafka -This example is based on the AWS docs for [Amazon MSK](https://docs.aws.amazon.com/lambda/latest/dg/with-msk.html){target="_blank" rel="nofollow"} and [self-managed Apache Kafka](https://docs.aws.amazon.com/lambda/latest/dg/with-kafka.html){target="_blank" rel="nofollow"}. +This example is based on the AWS docs for [Amazon MSK](https://docs.aws.amazon.com/lambda/latest/dg/with-msk.html){target="_blank"} and [self-managed Apache Kafka](https://docs.aws.amazon.com/lambda/latest/dg/with-kafka.html){target="_blank"}. === "app.py" @@ -1001,8 +1001,8 @@ function to access the data either as json or plain text, depending on the origi ### Rabbit MQ -It is used for [Rabbit MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank" rel="nofollow"}, also see -the [blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-for-rabbitmq-as-an-event-source-for-lambda/){target="_blank" rel="nofollow"} +It is used for [Rabbit MQ payloads](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html){target="_blank"}, also see +the [blog post](https://aws.amazon.com/blogs/compute/using-amazon-mq-for-rabbitmq-as-an-event-source-for-lambda/){target="_blank"} for more details. === "app.py" @@ -1047,7 +1047,7 @@ for more details. ### S3 Object Lambda -This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda – Use Your Code to Process Data as It Is Being Retrieved from S3](https://aws.amazon.com/blogs/aws/introducing-amazon-s3-object-lambda-use-your-code-to-process-data-as-it-is-being-retrieved-from-s3/){target="_blank" rel="nofollow"}. +This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda – Use Your Code to Process Data as It Is Being Retrieved from S3](https://aws.amazon.com/blogs/aws/introducing-amazon-s3-object-lambda-use-your-code-to-process-data-as-it-is-being-retrieved-from-s3/){target="_blank"}. === "app.py" @@ -1147,7 +1147,7 @@ This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda You can register your Lambda functions as targets within an Amazon VPC Lattice service network. By doing this, your Lambda function becomes a service within the network, and clients that have access to the VPC Lattice service network can call your service. -[Click here](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank" rel="nofollow"} for more information about using AWS Lambda with Amazon VPC Lattice. +[Click here](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"} for more information about using AWS Lambda with Amazon VPC Lattice. === "app.py" diff --git a/docs/utilities/feature_flags.md b/docs/utilities/feature_flags.md index 1b00cb46835..b68fcc594fb 100644 --- a/docs/utilities/feature_flags.md +++ b/docs/utilities/feature_flags.md @@ -6,7 +6,7 @@ description: Utility The feature flags utility provides a simple rule engine to define when one or multiple features should be enabled depending on the input. ???+ info - When using `AppConfigStore`, we currently only support AppConfig using [freeform configuration profile](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html#appconfig-creating-configuration-and-profile-free-form-configurations){target="_blank" rel="nofollow"} . + When using `AppConfigStore`, we currently only support AppConfig using [freeform configuration profile](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html#appconfig-creating-configuration-and-profile-free-form-configurations){target="_blank"} . ## Key features @@ -25,7 +25,7 @@ Feature flags are used to modify behaviour without changing the application's co **Dynamic flags**. Indicates something can have varying states, for example enable a list of premium features for customer X not Y. ???+ tip - You can use [Parameters utility](parameters.md){target="_blank" rel="nofollow"} for static flags while this utility can do both static and dynamic feature flags. + You can use [Parameters utility](parameters.md){target="_blank"} for static flags while this utility can do both static and dynamic feature flags. ???+ warning Be mindful that feature flags can increase the complexity of your application over time; use them sparingly. @@ -37,7 +37,7 @@ If you want to learn more about feature flags, their variations and trade-offs, * [Feature Flags Getting Started - CloudBees](https://www.cloudbees.com/blog/ultimate-feature-flag-guide){target="_blank" rel="nofollow"} ???+ note - AWS AppConfig requires two API calls to fetch configuration for the first time. You can improve latency by consolidating your feature settings in a single [Configuration](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html){target="_blank" rel="nofollow"}. + AWS AppConfig requires two API calls to fetch configuration for the first time. You can improve latency by consolidating your feature settings in a single [Configuration](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html){target="_blank"}. ## Getting started @@ -47,7 +47,7 @@ When using the default store `AppConfigStore`, your Lambda function IAM Role mus ### Required resources -By default, this utility provides [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank" rel="nofollow"} as a configuration store. +By default, this utility provides [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank"} as a configuration store. The following sample infrastructure will be used throughout this documentation: @@ -500,7 +500,7 @@ These are the available options for further customization. | **name** | `""` | AWS AppConfig Configuration name, e.g `features` | | **envelope** | `None` | JMESPath expression to use to extract feature flags configuration from AWS AppConfig configuration | | **max_age** | `5` | Number of seconds to cache feature flags configuration fetched from AWS AppConfig | -| **sdk_config** | `None` | [Botocore Config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank" rel="nofollow"} | +| **sdk_config** | `None` | [Botocore Config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank"} | | **jmespath_options** | `None` | For advanced use cases when you want to bring your own [JMESPath functions](https://github.com/jmespath/jmespath.py#custom-functions){target="_blank" rel="nofollow"} | | **logger** | `logging.Logger` | Logger to use for debug. You can optionally supply an instance of Powertools for AWS Lambda (Python) Logger. | @@ -577,6 +577,6 @@ You can unit test your feature flags locally and independently without setting u | Method | When to use | Requires new deployment on changes | Supported services | | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ----------------------------------------------------- | -| **[Environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html){target="_blank" rel="nofollow"}** | Simple configuration that will rarely if ever change, because changing it requires a Lambda function deployment. | Yes | Lambda | -| **[Parameters utility](parameters.md){target="_blank" rel="nofollow"}** | Access to secrets, or fetch parameters in different formats from AWS System Manager Parameter Store or Amazon DynamoDB. | No | Parameter Store, DynamoDB, Secrets Manager, AppConfig | +| **[Environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html){target="_blank"}** | Simple configuration that will rarely if ever change, because changing it requires a Lambda function deployment. | Yes | Lambda | +| **[Parameters utility](parameters.md){target="_blank"}** | Access to secrets, or fetch parameters in different formats from AWS System Manager Parameter Store or Amazon DynamoDB. | No | Parameter Store, DynamoDB, Secrets Manager, AppConfig | | **Feature flags utility** | Rule engine to define when one or multiple features should be enabled depending on the input. | No | AppConfig | diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index 0d018efaed1..1b2128cd7f0 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -94,14 +94,14 @@ If you're not [changing the default configuration for the DynamoDB persistence l ``` ???+ 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){target="_blank" rel="nofollow"}. + 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){target="_blank"}. 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/){target="_blank" rel="nofollow"} to + see 1WCU and 1RCU. Review the [DynamoDB pricing documentation](https://aws.amazon.com/dynamodb/pricing/){target="_blank"} to estimate the cost. ### Idempotent decorator @@ -135,7 +135,7 @@ Similar to [idempotent decorator](#idempotent-decorator), you can use `idempoten When using `idempotent_function`, you must tell us which keyword parameter in your function signature has the data we should use via **`data_keyword_argument`**. -!!! tip "We support JSON serializable data, [Python Dataclasses](https://docs.python.org/3.7/library/dataclasses.html){target="_blank" rel="nofollow"}, [Parser/Pydantic Models](parser.md){target="_blank" rel="nofollow"}, and our [Event Source Data Classes](./data_classes.md){target="_blank" rel="nofollow"}." +!!! tip "We support JSON serializable data, [Python Dataclasses](https://docs.python.org/3.7/library/dataclasses.html){target="_blank" rel="nofollow"}, [Parser/Pydantic Models](parser.md){target="_blank"}, and our [Event Source Data Classes](./data_classes.md){target="_blank"}." ???+ warning "Limitation" Make sure to call your decorated function using keyword arguments. @@ -154,7 +154,7 @@ When using `idempotent_function`, you must tell us which keyword parameter in yo #### Batch integration -You can can easily integrate with [Batch utility](batch.md){target="_blank" rel="nofollow"} via context manager. This ensures that you process each record in an idempotent manner, and guard against a [Lambda timeout](#lambda-timeouts) idempotent situation. +You can can easily integrate with [Batch utility](batch.md){target="_blank"} via context manager. This ensures that you process each record in an idempotent manner, and guard against a [Lambda timeout](#lambda-timeouts) idempotent situation. ???+ "Choosing an unique batch record attribute" In this example, we choose `messageId` as our idempotency key since we know it'll be unique. @@ -193,7 +193,7 @@ If we were to treat the entire request as our idempotency key, a simple HTTP hea The payload extracted by the `event_key_jmespath` is treated as a string by default. This means there could be differences in whitespace even when the JSON payload itself is identical. - To alter this behaviour, we can use the [JMESPath built-in function](jmespath_functions.md#powertools_json-function){target="_blank" rel="nofollow"} `powertools_json()` to treat the payload as a JSON object (dict) rather than a string. + To alter this behaviour, we can use the [JMESPath built-in function](jmespath_functions.md#powertools_json-function){target="_blank"} `powertools_json()` to treat the payload as a JSON object (dict) rather than a string. === "Payment function" @@ -212,7 +212,7 @@ If we were to treat the entire request as our idempotency key, a simple HTTP hea ???+ note This is automatically done when you decorate your Lambda handler with [@idempotent decorator](#idempotent-decorator). -To prevent against extended failed retries when a [Lambda function times out](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/){target="_blank" rel="nofollow"}, +To prevent against extended failed retries when a [Lambda function times out](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/){target="_blank"}, Powertools for AWS Lambda (Python) calculates and includes the remaining invocation available time as part of the idempotency record. ???+ example @@ -498,7 +498,7 @@ Idempotent decorator can be further configured with **`IdempotencyConfig`** as s | Parameter | Default | Description | | ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **event_key_jmespath** | `""` | JMESPath expression to extract the idempotency key from the event record using [built-in functions](/utilities/jmespath_functions){target="_blank" rel="nofollow"} | +| **event_key_jmespath** | `""` | JMESPath expression to extract the idempotency key from the event record using [built-in functions](/utilities/jmespath_functions){target="_blank"} | | **payload_validation_jmespath** | `""` | JMESPath expression to validate whether certain parameters have changed in the event while the event payload | | **raise_on_no_idempotency_key** | `False` | Raise exception if no idempotency key was found in the request | | **expires_after_seconds** | 3600 | The number of seconds to wait before a record is expired | @@ -561,7 +561,7 @@ You can change this window with the **`expires_after_seconds`** parameter: This will mark any records older than 5 minutes as expired, and [your function will be executed as normal if it is invoked with a matching payload](#expired-idempotency-records). ???+ important "Idempotency record expiration vs DynamoDB time-to-live (TTL)" - [DynamoDB TTL is a feature](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html){target="_blank" rel="nofollow"} to remove items after a certain period of time, it may occur within 48 hours of expiration. + [DynamoDB TTL is a feature](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html){target="_blank"} to remove items after a certain period of time, it may occur within 48 hours of expiration. We don't rely on DynamoDB or any persistence storage layer to determine whether a record is expired to avoid eventual inconsistency states. @@ -636,7 +636,7 @@ This means that we will raise **`IdempotencyKeyError`** if the evaluation of **` ### Customizing boto configuration -The **`boto_config`** and **`boto3_session`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank" rel="nofollow"} or a custom [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank" rel="nofollow"} when constructing the persistence store. +The **`boto_config`** and **`boto3_session`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank"} or a custom [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank"} when constructing the persistence store. === "Custom session" @@ -760,7 +760,7 @@ with a truthy value. If you prefer setting this for specific tests, and are usin ### Testing with DynamoDB Local -To test with [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html){target="_blank" rel="nofollow"}, you can replace the `DynamoDB client` used by the persistence layer with one you create inside your tests. This allows you to set the endpoint_url. +To test with [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html){target="_blank"}, you can replace the `DynamoDB client` used by the persistence layer with one you create inside your tests. This allows you to set the endpoint_url. === "test_with_dynamodb_local.py" @@ -776,7 +776,7 @@ To test with [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/ ### How do I mock all DynamoDB I/O operations -The idempotency utility lazily creates the dynamodb [Table](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank" rel="nofollow"} which it uses to access DynamoDB. +The idempotency utility lazily creates the dynamodb [Table](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank"} which it uses to access DynamoDB. This means it is possible to pass a mocked Table resource, or stub various methods. === "test_with_io_operations.py" @@ -794,4 +794,4 @@ This means it is possible to pass a mocked Table resource, or stub various metho ## Extra resources If you're interested in a deep dive on how Amazon uses idempotency when building our APIs, check out -[this article](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/){target="_blank" rel="nofollow"}. +[this article](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/){target="_blank"}. diff --git a/docs/utilities/jmespath_functions.md b/docs/utilities/jmespath_functions.md index ae1c40c35e1..881b4c926f7 100644 --- a/docs/utilities/jmespath_functions.md +++ b/docs/utilities/jmespath_functions.md @@ -19,11 +19,11 @@ Built-in [JMESPath](https://jmespath.org/){target="_blank" rel="nofollow"} Funct ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. You might have events that contains encoded JSON payloads as string, base64, or even in compressed format. It is a common use case to decode and extract them partially or fully as part of your Lambda function invocation. -Powertools for AWS Lambda (Python) also have utilities like [validation](validation.md){target="_blank" rel="nofollow"}, [idempotency](idempotency.md){target="_blank" rel="nofollow"}, or [feature flags](feature_flags.md){target="_blank" rel="nofollow"} where you might need to extract a portion of your data before using them. +Powertools for AWS Lambda (Python) also have utilities like [validation](validation.md){target="_blank"}, [idempotency](idempotency.md){target="_blank"}, or [feature flags](feature_flags.md){target="_blank"} where you might need to extract a portion of your data before using them. ???+ info "Terminology" **Envelope** is the terminology we use for the **JMESPath expression** to extract your JSON object from your data input. We might use those two terms interchangeably. @@ -120,7 +120,7 @@ This sample will deserialize the JSON string within the `data` key before valida > **Idempotency scenario** -This sample will deserialize the JSON string within the `body` key before [Idempotency](./idempotency.md){target="_blank" rel="nofollow"} processes it. +This sample will deserialize the JSON string within the `body` key before [Idempotency](./idempotency.md){target="_blank"} processes it. === "powertools_json_idempotency_jmespath.py" diff --git a/docs/utilities/middleware_factory.md b/docs/utilities/middleware_factory.md index 9ff3a6fb9c7..41670025b1e 100644 --- a/docs/utilities/middleware_factory.md +++ b/docs/utilities/middleware_factory.md @@ -15,7 +15,7 @@ Middleware factory provides a decorator factory to create your own middleware to ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. You might need a custom middleware to abstract non-functional code. These are often custom authorization or any reusable logic you might need to run before/after a Lambda function invocation. @@ -70,7 +70,7 @@ You can also have your own keyword arguments after the mandatory arguments. ## Advanced -For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target="_blank" rel="nofollow"} inside your middleware, and add annotations as well as metadata for additional operational insights. +For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target="_blank"} inside your middleware, and add annotations as well as metadata for additional operational insights. === "advanced_middleware_tracer_function.py" ```python hl_lines="7 9 12 16 17 19 25 42" @@ -87,12 +87,12 @@ For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target=" ### Tracing middleware **execution** -If you are making use of [Tracer](../core/tracer.md){target="_blank" rel="nofollow"}, you can trace the execution of your middleware to ease operations. +If you are making use of [Tracer](../core/tracer.md){target="_blank"}, you can trace the execution of your middleware to ease operations. This makes use of an existing Tracer instance that you may have initialized anywhere in your code. ???+ warning - You must [enable Active Tracing](../core/tracer/#permissions){target="_blank" rel="nofollow"} in your Lambda function when using this feature, otherwise Lambda cannot send traces to XRay. + You must [enable Active Tracing](../core/tracer/#permissions){target="_blank"} in your Lambda function when using this feature, otherwise Lambda cannot send traces to XRay. === "getting_started_middleware_tracer_function.py" ```python hl_lines="8 14 15 36" @@ -105,14 +105,14 @@ This makes use of an existing Tracer instance that you may have initialized anyw --8<-- "examples/middleware_factory/src/getting_started_middleware_tracer_payload.json" ``` -When executed, your middleware name will [appear in AWS X-Ray Trace details as](../core/tracer.md){target="_blank" rel="nofollow"} `## middleware_name`, in this example the middleware name is `## middleware_with_tracing`. +When executed, your middleware name will [appear in AWS X-Ray Trace details as](../core/tracer.md){target="_blank"} `## middleware_name`, in this example the middleware name is `## middleware_with_tracing`. ![Middleware simple Tracer](../media/middleware_factory_tracer_1.png) ### Combining Powertools for AWS Lambda (Python) utilities -You can create your own middleware and combine many features of Powertools for AWS Lambda (Python) such as [trace](../core/logger.md){target="_blank" rel="nofollow"}, [logs](../core/logger.md){target="_blank" rel="nofollow"}, [feature flags](feature_flags.md){target="_blank" rel="nofollow"}, [validation](validation.md){target="_blank" rel="nofollow"}, [jmespath_functions](jmespath_functions.md){target="_blank" rel="nofollow"} and others to abstract non-functional code. +You can create your own middleware and combine many features of Powertools for AWS Lambda (Python) such as [trace](../core/logger.md){target="_blank"}, [logs](../core/logger.md){target="_blank"}, [feature flags](feature_flags.md){target="_blank"}, [validation](validation.md){target="_blank"}, [jmespath_functions](jmespath_functions.md){target="_blank"} and others to abstract non-functional code. In the example below, we create a Middleware with the following features: diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index 867939da3f1..fa3241f43a8 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -4,7 +4,7 @@ description: Utility --- -The parameters utility provides high-level functions to retrieve one or multiple parameter values from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html){target="_blank" rel="nofollow"}, [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/){target="_blank" rel="nofollow"}, [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank" rel="nofollow"}, [Amazon DynamoDB](https://aws.amazon.com/dynamodb/){target="_blank" rel="nofollow"}, or bring your own. +The parameters utility provides high-level functions to retrieve one or multiple parameter values from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html){target="_blank"}, [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/){target="_blank"}, [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html){target="_blank"}, [Amazon DynamoDB](https://aws.amazon.com/dynamodb/){target="_blank"}, or bring your own. ## Key features @@ -16,7 +16,7 @@ The parameters utility provides high-level functions to retrieve one or multiple ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. By default, we fetch parameters from System Manager Parameter Store, secrets from Secrets Manager, and application configuration from AppConfig. @@ -304,7 +304,7 @@ You can create your own custom parameter store provider by inheriting the `BaseP All transformation and caching logic is handled by the `get()` and `get_multiple()` methods from the base provider class. -Here are two examples of implementing a custom parameter store. One using an external service like [Hashicorp Vault](https://www.vaultproject.io/){target="_blank" rel="nofollow"}, a widely popular key-value and secret storage and the other one using [Amazon S3](https://aws.amazon.com/s3/?nc1=h_ls){target="_blank" rel="nofollow"}, a popular object storage. +Here are two examples of implementing a custom parameter store. One using an external service like [Hashicorp Vault](https://www.vaultproject.io/){target="_blank" rel="nofollow"}, a widely popular key-value and secret storage and the other one using [Amazon S3](https://aws.amazon.com/s3/?nc1=h_ls){target="_blank"}, a popular object storage. === "working_with_own_provider_vault.py" ```python hl_lines="5 13 20 24" @@ -399,15 +399,15 @@ Here is the mapping between this utility's functions and methods and the underly | Provider | Function/Method | Client name | Function name | | ------------------- | ------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| SSM Parameter Store | `get_parameter` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank" rel="nofollow"} | -| SSM Parameter Store | `get_parameters` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank" rel="nofollow"} | -| SSM Parameter Store | `SSMProvider.get` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank" rel="nofollow"} | -| SSM Parameter Store | `SSMProvider.get_multiple` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank" rel="nofollow"} | -| Secrets Manager | `get_secret` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank" rel="nofollow"} | -| Secrets Manager | `SecretsProvider.get` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank" rel="nofollow"} | -| DynamoDB | `DynamoDBProvider.get` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank" rel="nofollow"}) | [get_item](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.get_item) | -| DynamoDB | `DynamoDBProvider.get_multiple` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank" rel="nofollow"}) | [query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.query) | -| App Config | `get_app_config` | `appconfigdata` | [start_configuration_session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.start_configuration_session){target="_blank" rel="nofollow"} and [get_latest_configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.get_latest_configuration){target="_blank" rel="nofollow"} | +| SSM Parameter Store | `get_parameter` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank"} | +| SSM Parameter Store | `get_parameters` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank"} | +| SSM Parameter Store | `SSMProvider.get` | `ssm` | [get_parameter](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameter){target="_blank"} | +| SSM Parameter Store | `SSMProvider.get_multiple` | `ssm` | [get_parameters_by_path](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_parameters_by_path){target="_blank"} | +| Secrets Manager | `get_secret` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank"} | +| Secrets Manager | `SecretsProvider.get` | `secretsmanager` | [get_secret_value](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/secretsmanager.html#SecretsManager.Client.get_secret_value){target="_blank"} | +| DynamoDB | `DynamoDBProvider.get` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank"}) | [get_item](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.get_item) | +| DynamoDB | `DynamoDBProvider.get_multiple` | `dynamodb` | ([Table resource](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table){target="_blank"}) | [query](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Table.query) | +| App Config | `get_app_config` | `appconfigdata` | [start_configuration_session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.start_configuration_session){target="_blank"} and [get_latest_configuration](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/appconfigdata.html#AppConfigData.Client.get_latest_configuration){target="_blank"} | ### Bring your own boto client @@ -432,7 +432,7 @@ Bringing them together in a single code snippet would look like this: ### Customizing boto configuration -The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank" rel="nofollow"}, [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank" rel="nofollow"}, or a [boto3 client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/boto3.html){target="_blank" rel="nofollow"} when constructing any of the built-in provider classes. +The **`config`** , **`boto3_session`**, and **`boto3_client`** parameters enable you to pass in a custom [botocore config object](https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html){target="_blank"}, [boto3 session](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html){target="_blank"}, or a [boto3 client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/boto3.html){target="_blank"} when constructing any of the built-in provider classes. ???+ tip You can use a custom session for retrieving parameters cross-account/region and for snapshot testing. diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 6abef997a5e..846460e43d2 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -21,7 +21,7 @@ Powertools for AWS Lambda (Python) supports Pydantic v1 and v2. Each Pydantic ve #### Using Pydantic v1 -!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank" rel="nofollow"}" +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" Add `aws-lambda-powertools[parser]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. @@ -35,7 +35,7 @@ Add `aws-lambda-powertools[parser]` as a dependency in your preferred tool: _e.g #### Using Pydantic v2 -You need to bring Pydantic v2.0.3 or later as an external dependency. Note that [we suppress Pydantic v2 deprecation warnings](https://github.com/aws-powertools/powertools-lambda-python/issues/2672){target="_blank" rel="nofollow"} to reduce noise and optimize log costs. +You need to bring Pydantic v2.0.3 or later as an external dependency. Note that [we suppress Pydantic v2 deprecation warnings](https://github.com/aws-powertools/powertools-lambda-python/issues/2672){target="_blank"} to reduce noise and optimize log costs. Add `aws-lambda-powertools` and `pydantic>=2.0.3` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. diff --git a/docs/utilities/streaming.md b/docs/utilities/streaming.md index 5c43bb8bc9b..49a114235af 100644 --- a/docs/utilities/streaming.md +++ b/docs/utilities/streaming.md @@ -185,6 +185,6 @@ Create an input payload using `io.BytesIO` and assert the response of the transf ### AWS X-Ray segment size limit -We make multiple API calls to S3 as you read chunks from your S3 object. If your function is decorated with [Tracer](./../core/tracer.md){target="_blank" rel="nofollow"}, you can easily hit [AWS X-Ray 64K segment size](https://docs.aws.amazon.com/general/latest/gr/xray.html#limits_xray){target="_blank" rel="nofollow"} when processing large files. +We make multiple API calls to S3 as you read chunks from your S3 object. If your function is decorated with [Tracer](./../core/tracer.md){target="_blank"}, you can easily hit [AWS X-Ray 64K segment size](https://docs.aws.amazon.com/general/latest/gr/xray.html#limits_xray){target="_blank"} when processing large files. !!! tip "Use tracer decorators in parts where you don't read your `S3Object` instead." diff --git a/docs/utilities/typing.md b/docs/utilities/typing.md index a76d53ab78a..9e2cc5024ab 100644 --- a/docs/utilities/typing.md +++ b/docs/utilities/typing.md @@ -18,9 +18,9 @@ This typing utility provides static typing classes that can be used to ease the ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. -We provide static typing for any context methods or properties implemented by [Lambda context object](https://docs.aws.amazon.com/lambda/latest/dg/python-context.html){target="_blank" rel="nofollow"}. +We provide static typing for any context methods or properties implemented by [Lambda context object](https://docs.aws.amazon.com/lambda/latest/dg/python-context.html){target="_blank"}. ## LambdaContext diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 7dc009db38d..7d822cf4b4c 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -16,7 +16,7 @@ This utility provides JSON Schema validation for events and responses, including ## Getting started ???+ tip - All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" rel="nofollow"}. + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank"}. You can validate inbound and outbound events using [`validator` decorator](#validator-decorator). @@ -32,7 +32,7 @@ You can also use the standalone `validate` function, if you want more control ov ### Install -!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank" rel="nofollow"}" +!!! info "This is not necessary if you're installing Powertools for AWS Lambda (Python) via [Lambda Layer/SAR](../index.md#lambda-layer){target="_blank"}" Add `aws-lambda-powertools[validation]` as a dependency in your preferred tool: _e.g._, _requirements.txt_, _pyproject.toml_. This will ensure you have the required dependencies before using Validation. @@ -194,7 +194,7 @@ For each format defined in a dictionary key, you must use a regex, or a function You might have events or responses that contain non-encoded JSON, where you need to decode before validating them. -You can use our built-in [JMESPath functions](./jmespath_functions.md){target="_blank" rel="nofollow"} within your expressions to do exactly that to [deserialize JSON Strings](./jmespath_functions.md#powertools_json-function){target="_blank" rel="nofollow"}, [decode base64](./jmespath_functions.md#powertools_base64-function){target="_blank" rel="nofollow"}, and [decompress gzip data](./jmespath_functions.md#powertools_base64_gzip-function){target="_blank" rel="nofollow"}. +You can use our built-in [JMESPath functions](./jmespath_functions.md){target="_blank"} within your expressions to do exactly that to [deserialize JSON Strings](./jmespath_functions.md#powertools_json-function){target="_blank"}, [decode base64](./jmespath_functions.md#powertools_base64-function){target="_blank"}, and [decompress gzip data](./jmespath_functions.md#powertools_base64_gzip-function){target="_blank"}. ???+ info We use these for [built-in envelopes](#built-in-envelopes) to easily to decode and unwrap events from sources like Kinesis, CloudWatch Logs, etc. From 920d70e99f9a9af33c401fbd23475c53a326a0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20D=C3=A9fosse?= <34415632+duc00@users.noreply.github.com> Date: Fri, 28 Jul 2023 19:18:29 +0200 Subject: [PATCH 22/92] docs(batch): explain record type discrepancy in failure and success handler (#2868) Co-authored-by: Heitor Lessa --- docs/utilities/batch.md | 17 +++++++++++------ ...ilure.py => extending_processor_handlers.py} | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) rename examples/batch_processing/src/{extending_failure.py => extending_processor_handlers.py} (79%) diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 0ef0a1366cb..ada05766ab4 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -522,14 +522,19 @@ You might want to bring custom logic to the existing `BatchProcessor` to slightl For these scenarios, you can subclass `BatchProcessor` and quickly override `success_handler` and `failure_handler` methods: -* **`success_handler()`** – Keeps track of successful batch records -* **`failure_handler()`** – Keeps track of failed batch records +* **`success_handler()`** is called for each successfully processed record +* **`failure_handler()`** is called for each failed record -???+ example - Let's suppose you'd like to add a metric named `BatchRecordFailures` for each batch record that failed processing +???+ note + These functions have a common `record` argument. For backward compatibility reasons, their type is not the same: -```python hl_lines="8 9 16-19 22 38" title="Extending failure handling mechanism in BatchProcessor" ---8<-- "examples/batch_processing/src/extending_failure.py" + - `success_handler`: `record` type is `dict[str, Any]`, the raw record data. + - `failure_handler`: `record` type can be an Event Source Data Class or your [Pydantic model](#pydantic-integration). During Pydantic validation errors, we fall back and serialize `record` to Event Source Data Class to not break the processing pipeline. + +Let's suppose you'd like to add metrics to track successes and failures of your batch records. + +```python hl_lines="8-10 18-25 28 44" title="Extending failure handling mechanism in BatchProcessor" +--8<-- "examples/batch_processing/src/extending_processor_handlers.py" ``` ### Create your own partial processor diff --git a/examples/batch_processing/src/extending_failure.py b/examples/batch_processing/src/extending_processor_handlers.py similarity index 79% rename from examples/batch_processing/src/extending_failure.py rename to examples/batch_processing/src/extending_processor_handlers.py index 424c9a5189b..73af5710981 100644 --- a/examples/batch_processing/src/extending_failure.py +++ b/examples/batch_processing/src/extending_processor_handlers.py @@ -1,4 +1,5 @@ import json +from typing import Any from aws_lambda_powertools import Logger, Metrics, Tracer from aws_lambda_powertools.metrics import MetricUnit @@ -9,11 +10,16 @@ FailureResponse, process_partial_response, ) +from aws_lambda_powertools.utilities.batch.base import SuccessResponse from aws_lambda_powertools.utilities.data_classes.sqs_event import SQSRecord from aws_lambda_powertools.utilities.typing import LambdaContext class MyProcessor(BatchProcessor): + def success_handler(self, record: dict[str, Any], result: Any) -> SuccessResponse: + metrics.add_metric(name="BatchRecordSuccesses", unit=MetricUnit.Count, value=1) + return super().success_handler(record, result) + def failure_handler(self, record: SQSRecord, exception: ExceptionInfo) -> FailureResponse: metrics.add_metric(name="BatchRecordFailures", unit=MetricUnit.Count, value=1) return super().failure_handler(record, exception) From e4ea10c47d5f712ec42951cccfb4302c52ba2faf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:03:24 +0100 Subject: [PATCH 23/92] chore(deps-dev): bump cfn-lint from 0.79.4 to 0.79.5 (#2870) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .../batch_processing/src/extending_processor_handlers.py | 4 ++-- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/batch_processing/src/extending_processor_handlers.py b/examples/batch_processing/src/extending_processor_handlers.py index 73af5710981..1e50c406c09 100644 --- a/examples/batch_processing/src/extending_processor_handlers.py +++ b/examples/batch_processing/src/extending_processor_handlers.py @@ -1,5 +1,5 @@ import json -from typing import Any +from typing import Any, Dict from aws_lambda_powertools import Logger, Metrics, Tracer from aws_lambda_powertools.metrics import MetricUnit @@ -16,7 +16,7 @@ class MyProcessor(BatchProcessor): - def success_handler(self, record: dict[str, Any], result: Any) -> SuccessResponse: + def success_handler(self, record: Dict[str, Any], result: Any) -> SuccessResponse: metrics.add_metric(name="BatchRecordSuccesses", unit=MetricUnit.Count, value=1) return super().success_handler(record, result) diff --git a/poetry.lock b/poetry.lock index a47307abccc..b63b42aed9c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -365,13 +365,13 @@ files = [ [[package]] name = "cfn-lint" -version = "0.79.4" +version = "0.79.5" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "cfn-lint-0.79.4.tar.gz", hash = "sha256:d4ddb83907b4d385ac958763486040591302f9aeb33d49b14399f580fddef1ae"}, - {file = "cfn_lint-0.79.4-py3-none-any.whl", hash = "sha256:86ca9873fefb40ccf321d0dc9b9c2fe1f6cc3aadb373bc10ae6fc5a54e37cf5b"}, + {file = "cfn-lint-0.79.5.tar.gz", hash = "sha256:7a00dba8f70b8a92c38bfc8f45e2ab20cedad5c49054a46f1ce931e48fc1cd0c"}, + {file = "cfn_lint-0.79.5-py3-none-any.whl", hash = "sha256:3054a2e407f77b3115c41de49fe2c11d728d53ab7be4ae478c1b5ff0e21331b7"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "f75331de0d0c9dadeeaf9a0bec41adfe9e124631bb5351d28575aa66c7a0a239" +content-hash = "569cc757c9b5d86c44935c9a48f24e8ca32fdb83a1139e3e1c6673822f676daa" diff --git a/pyproject.toml b/pyproject.toml index 10e67e6e520..6ddca5b49db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ all = ["pydantic", "aws-xray-sdk", "fastjsonschema"] aws-sdk = ["boto3"] [tool.poetry.group.dev.dependencies] -cfn-lint = "0.79.4" +cfn-lint = "0.79.5" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" From f951ee680ae461aa4446f2936be842fdb95fcb03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:05:17 +0100 Subject: [PATCH 24/92] chore(deps): bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer (#2877) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 2 +- layer/scripts/layer-balancer/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index d4cab54bf5f..d2ce3e15f64 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -3,7 +3,7 @@ module layerbalancer go 1.18 require ( - github.com/aws/aws-sdk-go-v2 v1.19.0 + github.com/aws/aws-sdk-go-v2 v1.19.1 github.com/aws/aws-sdk-go-v2/config v1.18.29 github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 2208e8c0750..6ac4a6ba3e0 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,5 +1,6 @@ -github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= +github.com/aws/aws-sdk-go-v2 v1.19.1 h1:STs0lbbpXu3byTPcnRLghs2DH0yk9qKDo27TyyJSKsM= +github.com/aws/aws-sdk-go-v2 v1.19.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= github.com/aws/aws-sdk-go-v2/config v1.18.29 h1:yA+bSSRGhBwWuprG9I4VgxfK//NBLZ/0BGOHiV3f9oM= From 4d179e5fd456e345bd5da392f318c5c6e91eecf1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:05:41 +0100 Subject: [PATCH 25/92] chore(deps): bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer (#2876) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 6 +++--- layer/scripts/layer-balancer/go.sum | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index d2ce3e15f64..b7e3fcc6c3b 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.19.1 github.com/aws/aws-sdk-go-v2/config v1.18.29 - github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0 + github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) @@ -14,8 +14,8 @@ require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.28 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 6ac4a6ba3e0..14f6582eaa9 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -9,16 +9,18 @@ github.com/aws/aws-sdk-go-v2/credentials v1.13.28 h1:WM9tEHgoOh5ThJZ042UKnSx7TXG github.com/aws/aws-sdk-go-v2/credentials v1.13.28/go.mod h1:86BSbSeamnVVdr1hPfBZVN8SXM7KxSAZAvhNxVfi8fU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 h1:kbk81RlPoC6e4co7cQx2FAvH9TgbzxIqCqiosAFiB+w= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36/go.mod h1:T8Jsn/uNL/AFOXrVYQ1YQaN1r9gN34JU1855/Lyjv+o= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 h1:lMl8S5SB8jNCB+Sty2Em4lnu3IJytceHQd7qbmfqKL0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30/go.mod h1:v3GSCnFxbHzt9dlWBqvA1K1f9lmWuf4ztupZBCAIVs4= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4= -github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0 h1:vgYsSbb7WICagS9pelgqG+CjPK2blsCMEqjTlU6RPEM= -github.com/aws/aws-sdk-go-v2/service/lambda v1.38.0/go.mod h1:zmdE2b9ZX8milexhZc3SeC3LwJRJpJ0k0fsuMBOSCEI= +github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1 h1:Z5xcDDVsL0tXrKyZJ6CobEEMOMON9/il//sOzek5R3c= +github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1/go.mod h1:6cGKLOGI3AgEnayDbxST1ixo5lwpoQHcPg0wAUO4DBU= github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k= github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= From bfcb5e6b65eb2cd6822e87661eda612a87646c86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:09:00 +0100 Subject: [PATCH 26/92] chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer (#2875) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 16 ++++++------- layer/scripts/layer-balancer/go.sum | 35 +++++++++++++---------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index b7e3fcc6c3b..8c98514049c 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.19.1 - github.com/aws/aws-sdk-go-v2/config v1.18.29 + github.com/aws/aws-sdk-go-v2/config v1.18.30 github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 @@ -12,15 +12,15 @@ require ( require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.28 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.29 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.20.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.14 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.20.1 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 14f6582eaa9..e909d964b93 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,32 +1,29 @@ -github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.19.1 h1:STs0lbbpXu3byTPcnRLghs2DH0yk9qKDo27TyyJSKsM= github.com/aws/aws-sdk-go-v2 v1.19.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= -github.com/aws/aws-sdk-go-v2/config v1.18.29 h1:yA+bSSRGhBwWuprG9I4VgxfK//NBLZ/0BGOHiV3f9oM= -github.com/aws/aws-sdk-go-v2/config v1.18.29/go.mod h1:bJT6P8A+KU1qvNMp8aj+/NmaI06Z670dHNoWsrLOgMg= -github.com/aws/aws-sdk-go-v2/credentials v1.13.28 h1:WM9tEHgoOh5ThJZ042UKnSx7TXGSC/bz63X3fsrQL2o= -github.com/aws/aws-sdk-go-v2/credentials v1.13.28/go.mod h1:86BSbSeamnVVdr1hPfBZVN8SXM7KxSAZAvhNxVfi8fU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 h1:kP3Me6Fy3vdi+9uHd7YLr6ewPxRL+PU6y15urfTaamU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5/go.mod h1:Gj7tm95r+QsDoN2Fhuz/3npQvcZbkEf5mL70n3Xfluc= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= +github.com/aws/aws-sdk-go-v2/config v1.18.30 h1:TTAXQIn31qYFUQjkW6siVrRTX1ux+sADZDOe3jsZcMg= +github.com/aws/aws-sdk-go-v2/config v1.18.30/go.mod h1:+YogjT7e/t9JVu/sOnZZgxTge1G+bPNk8zOaI0QIQvE= +github.com/aws/aws-sdk-go-v2/credentials v1.13.29 h1:KNgCpThGuZyCjq9EuuqoLDenKKMwO/x1Xx01ckDa7VI= +github.com/aws/aws-sdk-go-v2/credentials v1.13.29/go.mod h1:VMq1LcmSEa9qxBlOCYTjVuGJWEEzhGmgL552jQsmhss= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6 h1:kortK122LvTU34CGX/F9oJpelXKkEA2j/MW48II+8+8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6/go.mod h1:k7IPHyHNIASI0m0RwOmCjWOTtgG+J0raqwuHH8WhWJE= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 h1:kbk81RlPoC6e4co7cQx2FAvH9TgbzxIqCqiosAFiB+w= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36/go.mod h1:T8Jsn/uNL/AFOXrVYQ1YQaN1r9gN34JU1855/Lyjv+o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 h1:lMl8S5SB8jNCB+Sty2Em4lnu3IJytceHQd7qbmfqKL0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30/go.mod h1:v3GSCnFxbHzt9dlWBqvA1K1f9lmWuf4ztupZBCAIVs4= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 h1:8r5m1BoAWkn0TDC34lUculryf7nUF25EgIMdjvGCkgo= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36/go.mod h1:Rmw2M1hMVTwiUhjwMoIBFWFJMhvJbct06sSidxInkhY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 h1:IiDolu/eLmuB18DRZibj77n1hHQT7z12jnGO7Ze3pLc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29/go.mod h1:fDbkK4o7fpPXWn8YAPmTieAMuB9mk/VgvW64uaUqxd4= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37 h1:BXiqvN7WuV/pMhz8CivhO8cG8icJcjnjHumif4ukQ0c= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37/go.mod h1:d4GZ62cjnz/hjKFdAu11gAwK73bdhqaFv2O4J1gaqIs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30 h1:UcVZxLVNY4yayCmiG94Ge3l2qbc5WEB/oa4RmjoQEi0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30/go.mod h1:wPffyJiWWtHwvpFyn23WjAjVjMnlQOQrl02+vutBh3Y= github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1 h1:Z5xcDDVsL0tXrKyZJ6CobEEMOMON9/il//sOzek5R3c= github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1/go.mod h1:6cGKLOGI3AgEnayDbxST1ixo5lwpoQHcPg0wAUO4DBU= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 h1:sWDv7cMITPcZ21QdreULwxOOAmE05JjEsT6fCDtDA9k= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.13/go.mod h1:DfX0sWuT46KpcqbMhJ9QWtxAIP1VozkDWf8VAkByjYY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 h1:BFubHS/xN5bjl818QaroN6mQdjneYQ+AOx44KNXlyH4= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13/go.mod h1:BzqsVVFduubEmzrVtUFQQIQdFqvUItF8XUq2EnS8Wog= -github.com/aws/aws-sdk-go-v2/service/sts v1.20.0 h1:jKmIOO+dFvCPuIhhM8u0Dy3dtd590n2kEDSYiGHoI98= -github.com/aws/aws-sdk-go-v2/service/sts v1.20.0/go.mod h1:yVGZA1CPkmUhBdA039jXNJJG7/6t+G+EBWmFq23xqnY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.14 h1:gUjz7trfz9qBm0AlkKTvJHBXELi1wvw+2LA9GfD2AsM= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.14/go.mod h1:9kfRdJgLCbnyeqZ/DpaSwcgj9ZDYLfRpe8Sze+NrYfQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14 h1:8bEtxV5UT9ucdWGXfZ7CM3caQhSHGjWnTHt0OeF7m7s= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14/go.mod h1:nd9BG2UnexN2sDx/mk2Jd6pf3d2E61AiA8m8Fdvdx8Y= +github.com/aws/aws-sdk-go-v2/service/sts v1.20.1 h1:U7h9CPoyMfVoN5jUglB0LglCMP10AK4vMBsbsCKM8Yw= +github.com/aws/aws-sdk-go-v2/service/sts v1.20.1/go.mod h1:BUHusg4cOA1TFGegj7x8/eoWrbdHzJfoMrXcbMQAG0k= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From 7d199f4526fdc904d4b306de0cc8f3173492e549 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:28:31 +0100 Subject: [PATCH 27/92] chore(deps-dev): bump mypy-boto3-xray from 1.28.0 to 1.28.15 (#2881) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index b63b42aed9c..f8689d3ccbb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1568,13 +1568,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-xray" -version = "1.28.0" -description = "Type annotations for boto3.XRay 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.15" +description = "Type annotations for boto3.XRay 1.28.15 service generated with mypy-boto3-builder 7.16.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-xray-1.28.0.tar.gz", hash = "sha256:8ce07598f7eeabe66e8dc8cb7e906efb96198b9102f58e9315e6daf166abf3e7"}, - {file = "mypy_boto3_xray-1.28.0-py3-none-any.whl", hash = "sha256:64cd601a829c274665b977853f85b27464986e9eec1ebc03f5bc4530a400b2f6"}, + {file = "mypy-boto3-xray-1.28.15.tar.gz", hash = "sha256:ace907f4637a3a65b7645b8813599436940d31bd72ea61f9cd24ccf608a43f0e"}, + {file = "mypy_boto3_xray-1.28.15-py3-none-any.whl", hash = "sha256:6b5fde53dc8d93b04190792466bc122c83acb8534ce83e3eafdc5d9af1d632af"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "569cc757c9b5d86c44935c9a48f24e8ca32fdb83a1139e3e1c6673822f676daa" +content-hash = "c353c640d8de3e8cb93ff363750ac80fcc771cc8cc273b1ba592b9748db045d3" diff --git a/pyproject.toml b/pyproject.toml index 6ddca5b49db..61b344cdeb8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,7 @@ mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.28.3" mypy-boto3-ssm = "^1.28.12" mypy-boto3-s3 = "^1.28.8" -mypy-boto3-xray = "^1.28.0" +mypy-boto3-xray = "^1.28.15" types-requests = "^2.31.0" typing-extensions = "^4.6.2" mkdocs-material = "^9.1.19" From bdc2132950057716fbbdc672f12555c9ac83a759 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:43:36 +0100 Subject: [PATCH 28/92] chore(deps-dev): bump mypy-boto3-lambda from 1.28.11 to 1.28.15 (#2878) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index f8689d3ccbb..f4fa9b822a3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1498,13 +1498,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-lambda" -version = "1.28.11" -description = "Type annotations for boto3.Lambda 1.28.11 service generated with mypy-boto3-builder 7.15.1" +version = "1.28.15" +description = "Type annotations for boto3.Lambda 1.28.15 service generated with mypy-boto3-builder 7.16.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.28.11.tar.gz", hash = "sha256:2df51192be0ff1d37b3d34ffc8e5849e352e812c65fd79b1fa85c439367e478f"}, - {file = "mypy_boto3_lambda-1.28.11-py3-none-any.whl", hash = "sha256:8449b569b7cb387d2be3b8db584f60789f08fe61866d11f8b8d64b2431989a18"}, + {file = "mypy-boto3-lambda-1.28.15.tar.gz", hash = "sha256:9f063ddf67be8b5d9d8bb5a6e072d7aff22eebfca25f2d8f7b9cf351e18d9937"}, + {file = "mypy_boto3_lambda-1.28.15-py3-none-any.whl", hash = "sha256:b189c948e41b86b80f84fe14f438c4cedfb81697039c4b1c01871a2aee3415a8"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "c353c640d8de3e8cb93ff363750ac80fcc771cc8cc273b1ba592b9748db045d3" +content-hash = "1c2f547e6ca9176c58c11eedee6a6138304cb5bf5070af981dd98e292378e6fd" diff --git a/pyproject.toml b/pyproject.toml index 61b344cdeb8..b4c85f20737 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ mypy-boto3-appconfig = "^1.28.12" mypy-boto3-cloudformation = "^1.28.12" mypy-boto3-cloudwatch = "^1.28.12" mypy-boto3-dynamodb = "^1.28.11" -mypy-boto3-lambda = "^1.28.11" +mypy-boto3-lambda = "^1.28.15" mypy-boto3-logs = "^1.28.1" mypy-boto3-secretsmanager = "^1.28.3" mypy-boto3-ssm = "^1.28.12" From ac8df33b6bdd69a40a60ae0743aa3f9b7a5e256f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:57:10 +0100 Subject: [PATCH 29/92] chore(deps-dev): bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 (#2879) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index f4fa9b822a3..f33ff08f421 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1442,13 +1442,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-appconfigdata" -version = "1.28.0" -description = "Type annotations for boto3.AppConfigData 1.28.0 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.15" +description = "Type annotations for boto3.AppConfigData 1.28.15 service generated with mypy-boto3-builder 7.16.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfigdata-1.28.0.tar.gz", hash = "sha256:1f0331fcb6642c44d335d08250ee5abcd840030304d480adf85ea017ba941bb4"}, - {file = "mypy_boto3_appconfigdata-1.28.0-py3-none-any.whl", hash = "sha256:c01ecbbda949497dbb650cc761915a7e14b621db5bc20cc1fd3f49620e74c9bc"}, + {file = "mypy-boto3-appconfigdata-1.28.15.tar.gz", hash = "sha256:ce6ee92c180c6fd7ac03dfd6a4502164c014b89c59a1e0f67aab88bc96895098"}, + {file = "mypy_boto3_appconfigdata-1.28.15-py3-none-any.whl", hash = "sha256:76f4a37fd0cfd9106496ddda39e198e75f139fb055d79aac582ed44e08c8b71b"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "1c2f547e6ca9176c58c11eedee6a6138304cb5bf5070af981dd98e292378e6fd" +content-hash = "68e3d74f95dab29887d847838e02827edfe40e95ef91d2c6b13d8f806f53c7cb" diff --git a/pyproject.toml b/pyproject.toml index b4c85f20737..4c982f68045 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ typing-extensions = "^4.6.2" mkdocs-material = "^9.1.19" filelock = "^3.12.2" checksumdir = "^1.2.0" -mypy-boto3-appconfigdata = "^1.28.0" +mypy-boto3-appconfigdata = "^1.28.15" ijson = "^3.2.2" typed-ast = { version = "^1.5.5", python = "< 3.8"} hvac = "^1.1.1" From 6d3043390a48c6ea8a8b8e38ae298073f2351771 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 23:16:19 +0100 Subject: [PATCH 30/92] chore(deps-dev): bump mypy-boto3-logs from 1.28.1 to 1.28.15 (#2880) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index f33ff08f421..04ec86dec3c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1512,13 +1512,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-logs" -version = "1.28.1" -description = "Type annotations for boto3.CloudWatchLogs 1.28.1 service generated with mypy-boto3-builder 7.14.5" +version = "1.28.15" +description = "Type annotations for boto3.CloudWatchLogs 1.28.15 service generated with mypy-boto3-builder 7.16.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-logs-1.28.1.tar.gz", hash = "sha256:e0278a977d68c15120c0f2f4a85b46d0ca3e17c676c7d218dbbb3cfa1b4c8ef1"}, - {file = "mypy_boto3_logs-1.28.1-py3-none-any.whl", hash = "sha256:0ab3b7b39f1c3b0d530096fe2bfb9df09b989b0ea718e5ecbf823c32b016e319"}, + {file = "mypy-boto3-logs-1.28.15.tar.gz", hash = "sha256:0208dbb873ad252258cc025e4598a14ef9ecae3623468cf8f82d3d7bcfafae7b"}, + {file = "mypy_boto3_logs-1.28.15-py3-none-any.whl", hash = "sha256:245cbf1ba6f2bdc8be1260d8991686eda5585f8c6c6c4b783c82b3568950e84c"}, ] [package.dependencies] @@ -2692,4 +2692,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "68e3d74f95dab29887d847838e02827edfe40e95ef91d2c6b13d8f806f53c7cb" +content-hash = "87dd8a10659154c79e999c181f679a309dcd6891f8e4a3e2f0935d9c9c47e14a" diff --git a/pyproject.toml b/pyproject.toml index 4c982f68045..c3227878b6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ mypy-boto3-cloudformation = "^1.28.12" mypy-boto3-cloudwatch = "^1.28.12" mypy-boto3-dynamodb = "^1.28.11" mypy-boto3-lambda = "^1.28.15" -mypy-boto3-logs = "^1.28.1" +mypy-boto3-logs = "^1.28.15" mypy-boto3-secretsmanager = "^1.28.3" mypy-boto3-ssm = "^1.28.12" mypy-boto3-s3 = "^1.28.8" From 66d4c76f00febbf519227fcdcd34166fa163df66 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 29 Jul 2023 23:14:43 +0100 Subject: [PATCH 31/92] chore(ci): changelog rebuild (#2883) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7db41bc6c73..d48616e581e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,23 +10,34 @@ ## Documentation +* **batch:** explain record type discrepancy in failure and success handler ([#2868](https://github.com/aws-powertools/powertools-lambda-python/issues/2868)) * **batch:** new visuals and error handling section ([#2857](https://github.com/aws-powertools/powertools-lambda-python/issues/2857)) +* **navigation:** remove nofollow attribute for internal links ([#2867](https://github.com/aws-powertools/powertools-lambda-python/issues/2867)) * **navigation:** add nofollow attribute ([#2842](https://github.com/aws-powertools/powertools-lambda-python/issues/2842)) * **tutorial:** add support for Python 3.11 ([#2860](https://github.com/aws-powertools/powertools-lambda-python/issues/2860)) ## Maintenance +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) -* **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) +* **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) +* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) From 4fe499a6cd2ce1833e6fa2ef8853b7d6bf54314a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:02:47 +0200 Subject: [PATCH 32/92] chore(ci): changelog rebuild (#2885) --- CHANGELOG.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d48616e581e..a9b4870691a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,26 +18,26 @@ ## Maintenance -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) * **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) -* **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) -* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) -* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) +* **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) From 00e2e84d469caedbc81b19e0d1b47d6f71de0d8d Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 1 Aug 2023 10:47:44 +0200 Subject: [PATCH 33/92] chore(ci): group dependabot updates (#2896) --- .github/dependabot.yml | 51 +++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2ed1322608a..fed13e3e577 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,5 @@ version: 2 updates: - - package-ecosystem: "github-actions" directory: "/" schedule: @@ -20,6 +19,10 @@ updates: ignore: # 2022-04-23: Ignoring boto3 changes until we need to care about them. - dependency-name: "boto3" + groups: + boto-typing: + patterns: + - "mypy-boto3-*" - package-ecosystem: "npm" directory: "/" @@ -33,46 +36,54 @@ updates: # Allow updates for AWS CDK - dependency-name: "aws-cdk" -# - package-ecosystem: "pip" -# directory: "/" -# schedule: -# interval: "daily" -# target-branch: "develop" -# update_types: -# - "semver:major" -# labels: -# - "do-not-merge" -# - "dependencies" -# commit-message: -# prefix: chore -# include: scope - - package-ecosystem: pip directory: /benchmark/src/instrumented + commit-message: + prefix: chore + include: scope schedule: interval: daily - package-ecosystem: pip directory: /benchmark/src/reference + commit-message: + prefix: chore + include: scope schedule: interval: daily - package-ecosystem: docker directory: /docs + commit-message: + prefix: chore + include: scope schedule: interval: daily - package-ecosystem: pip - directory: /examples/event_handler_graphql/src + directory: /docs + commit-message: + prefix: chore + include: scope schedule: interval: daily - - package-ecosystem: gomod - directory: /layer/scripts/layer-balancer + - package-ecosystem: pip + directory: /examples/event_handler_graphql/src + commit-message: + prefix: chore + include: scope schedule: interval: daily - - package-ecosystem: pip - directory: /docs + - package-ecosystem: gomod + directory: /layer/scripts/layer-balancer + commit-message: + prefix: chore + include: scope schedule: interval: daily + groups: + layer-balancer: + patterns: + - "*" From 18b268a6957bfc79e0eaaa7ae8b987ab753379f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:48:22 +0200 Subject: [PATCH 34/92] chore(deps-dev): bump mkdocs-material from 9.1.19 to 9.1.21 (#2894) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 23 +++++++++++++---------- pyproject.toml | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/poetry.lock b/poetry.lock index 04ec86dec3c..b8521c3ca9c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1287,13 +1287,13 @@ test = ["coverage", "flake8 (>=3.0)", "shtab"] [[package]] name = "mkdocs" -version = "1.4.3" +version = "1.5.1" description = "Project documentation with Markdown." optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs-1.4.3-py3-none-any.whl", hash = "sha256:6ee46d309bda331aac915cd24aab882c179a933bd9e77b80ce7d2eaaa3f689dd"}, - {file = "mkdocs-1.4.3.tar.gz", hash = "sha256:5955093bbd4dd2e9403c5afaf57324ad8b04f16886512a3ee6ef828956481c57"}, + {file = "mkdocs-1.5.1-py3-none-any.whl", hash = "sha256:67e889f8d8ba1fe5decdfc59f5f8f21d6a8925a129339e93dede303bdea03a98"}, + {file = "mkdocs-1.5.1.tar.gz", hash = "sha256:f2f323c62fffdf1b71b84849e39aef56d6852b3f0a5571552bca32cefc650209"}, ] [package.dependencies] @@ -1302,9 +1302,12 @@ colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} jinja2 = ">=2.11.1" -markdown = ">=3.2.1,<3.4" +markdown = ">=3.2.1" +markupsafe = ">=2.0.1" mergedeep = ">=1.3.4" packaging = ">=20.5" +pathspec = ">=0.11.1" +platformdirs = ">=2.2.0" pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" typing-extensions = {version = ">=3.10", markers = "python_version < \"3.8\""} @@ -1312,7 +1315,7 @@ watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] [[package]] name = "mkdocs-git-revision-date-plugin" @@ -1331,20 +1334,20 @@ mkdocs = ">=0.17" [[package]] name = "mkdocs-material" -version = "9.1.19" +version = "9.1.21" description = "Documentation that simply works" optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs_material-9.1.19-py3-none-any.whl", hash = "sha256:fb0a149294b319aedf36983919d8c40c9e566db21ead16258e20ebd2e6c0961c"}, - {file = "mkdocs_material-9.1.19.tar.gz", hash = "sha256:73b94b08c765e92a80645aac58d6a741fc5f587deec2b715489c714827b15a6f"}, + {file = "mkdocs_material-9.1.21-py3-none-any.whl", hash = "sha256:58bb2f11ef240632e176d6f0f7d1cff06be1d11c696a5a1b553b808b4280ed47"}, + {file = "mkdocs_material-9.1.21.tar.gz", hash = "sha256:71940cdfca84ab296b6362889c25395b1621273fb16c93deda257adb7ff44ec8"}, ] [package.dependencies] colorama = ">=0.4" jinja2 = ">=3.0" markdown = ">=3.2" -mkdocs = ">=1.4.2" +mkdocs = ">=1.5.0" mkdocs-material-extensions = ">=1.1" pygments = ">=2.14" pymdown-extensions = ">=9.9.1" @@ -2692,4 +2695,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "87dd8a10659154c79e999c181f679a309dcd6891f8e4a3e2f0935d9c9c47e14a" +content-hash = "03df7cb4d0cb94d716ed188bec7269a14e5b750fddbfbe38c0fd9f768ca1eb37" diff --git a/pyproject.toml b/pyproject.toml index c3227878b6c..bf03ce84bd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ mypy-boto3-s3 = "^1.28.8" mypy-boto3-xray = "^1.28.15" types-requests = "^2.31.0" typing-extensions = "^4.6.2" -mkdocs-material = "^9.1.19" +mkdocs-material = "^9.1.21" filelock = "^3.12.2" checksumdir = "^1.2.0" mypy-boto3-appconfigdata = "^1.28.15" From 8275d2370574374f49ea773ed9d8db1ccb29ec51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:49:31 +0200 Subject: [PATCH 35/92] chore(deps): bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer (#2890) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 12 ++++++------ layer/scripts/layer-balancer/go.sum | 20 ++++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 8c98514049c..bdc8a7f59ae 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -3,24 +3,24 @@ module layerbalancer go 1.18 require ( - github.com/aws/aws-sdk-go-v2 v1.19.1 + github.com/aws/aws-sdk-go-v2 v1.20.0 github.com/aws/aws-sdk-go-v2/config v1.18.30 - github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1 + github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) require ( - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.13.29 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.12.14 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.20.1 // indirect - github.com/aws/smithy-go v1.13.5 // indirect + github.com/aws/smithy-go v1.14.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index e909d964b93..d32dd1c4350 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,31 +1,35 @@ -github.com/aws/aws-sdk-go-v2 v1.19.1 h1:STs0lbbpXu3byTPcnRLghs2DH0yk9qKDo27TyyJSKsM= github.com/aws/aws-sdk-go-v2 v1.19.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno= +github.com/aws/aws-sdk-go-v2 v1.20.0 h1:INUDpYLt4oiPOJl0XwZDK2OVAVf0Rzo+MGVTv9f+gy8= +github.com/aws/aws-sdk-go-v2 v1.20.0/go.mod h1:uWOr0m0jDsiWw8nnXiqZ+YG6LdvAlGYDLLf2NmHZoy4= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 h1:/MS8AzqYNAhhRNalOmxUvYs8VEbNGifTnzhPFdcRQkQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11/go.mod h1:va22++AdXht4ccO3kH2SHkHHYvZ2G9Utz+CXKmm2CaU= github.com/aws/aws-sdk-go-v2/config v1.18.30 h1:TTAXQIn31qYFUQjkW6siVrRTX1ux+sADZDOe3jsZcMg= github.com/aws/aws-sdk-go-v2/config v1.18.30/go.mod h1:+YogjT7e/t9JVu/sOnZZgxTge1G+bPNk8zOaI0QIQvE= github.com/aws/aws-sdk-go-v2/credentials v1.13.29 h1:KNgCpThGuZyCjq9EuuqoLDenKKMwO/x1Xx01ckDa7VI= github.com/aws/aws-sdk-go-v2/credentials v1.13.29/go.mod h1:VMq1LcmSEa9qxBlOCYTjVuGJWEEzhGmgL552jQsmhss= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6 h1:kortK122LvTU34CGX/F9oJpelXKkEA2j/MW48II+8+8= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6/go.mod h1:k7IPHyHNIASI0m0RwOmCjWOTtgG+J0raqwuHH8WhWJE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36 h1:kbk81RlPoC6e4co7cQx2FAvH9TgbzxIqCqiosAFiB+w= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36/go.mod h1:T8Jsn/uNL/AFOXrVYQ1YQaN1r9gN34JU1855/Lyjv+o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30 h1:lMl8S5SB8jNCB+Sty2Em4lnu3IJytceHQd7qbmfqKL0= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 h1:zr/gxAZkMcvP71ZhQOcvdm8ReLjFgIXnIn0fw5AM7mo= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37/go.mod h1:Pdn4j43v49Kk6+82spO3Tu5gSeQXRsxo56ePPQAvFiA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30/go.mod h1:v3GSCnFxbHzt9dlWBqvA1K1f9lmWuf4ztupZBCAIVs4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 h1:0HCMIkAkVY9KMgueD8tf4bRTUanzEYvhw7KkPXIMpO0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31/go.mod h1:fTJDMe8LOFYtqiFFFeHA+SVMAwqLhoq0kcInYoLa9Js= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37 h1:BXiqvN7WuV/pMhz8CivhO8cG8icJcjnjHumif4ukQ0c= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37/go.mod h1:d4GZ62cjnz/hjKFdAu11gAwK73bdhqaFv2O4J1gaqIs= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30 h1:UcVZxLVNY4yayCmiG94Ge3l2qbc5WEB/oa4RmjoQEi0= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30/go.mod h1:wPffyJiWWtHwvpFyn23WjAjVjMnlQOQrl02+vutBh3Y= -github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1 h1:Z5xcDDVsL0tXrKyZJ6CobEEMOMON9/il//sOzek5R3c= -github.com/aws/aws-sdk-go-v2/service/lambda v1.38.1/go.mod h1:6cGKLOGI3AgEnayDbxST1ixo5lwpoQHcPg0wAUO4DBU= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0 h1:CDDjp86If1TkvURnNMWcYZpbG+WAGdfO7AWlrwWJ3dk= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0/go.mod h1:MiY958jauOEVweMj4Xxa81B45wTg/6ewgp3XeCLV+hg= github.com/aws/aws-sdk-go-v2/service/sso v1.12.14 h1:gUjz7trfz9qBm0AlkKTvJHBXELi1wvw+2LA9GfD2AsM= github.com/aws/aws-sdk-go-v2/service/sso v1.12.14/go.mod h1:9kfRdJgLCbnyeqZ/DpaSwcgj9ZDYLfRpe8Sze+NrYfQ= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14 h1:8bEtxV5UT9ucdWGXfZ7CM3caQhSHGjWnTHt0OeF7m7s= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14/go.mod h1:nd9BG2UnexN2sDx/mk2Jd6pf3d2E61AiA8m8Fdvdx8Y= github.com/aws/aws-sdk-go-v2/service/sts v1.20.1 h1:U7h9CPoyMfVoN5jUglB0LglCMP10AK4vMBsbsCKM8Yw= github.com/aws/aws-sdk-go-v2/service/sts v1.20.1/go.mod h1:BUHusg4cOA1TFGegj7x8/eoWrbdHzJfoMrXcbMQAG0k= -github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.14.0 h1:+X90sB94fizKjDmwb4vyl2cTTPXTE5E2G/1mjByb0io= +github.com/aws/smithy-go v1.14.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= From c900ba25fecfd2205fbea9b81e7dee896404101e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:50:22 +0200 Subject: [PATCH 36/92] chore(deps-dev): bump aws-cdk from 2.88.0 to 2.89.0 (#2887) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64ddf8ac968..8f706475180 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,13 @@ "package-lock.json": "^1.0.0" }, "devDependencies": { - "aws-cdk": "^2.88.0" + "aws-cdk": "^2.89.0" } }, "node_modules/aws-cdk": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.88.0.tgz", - "integrity": "sha512-7Tj0uusA2nsEOsqkd4kB5vmzciz7l/eGBN5a+Ce4/CCcoe4ZCvT85L+T6tK0aohUTLZTAlTPBceH34RN5iMYpA==", + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.89.0.tgz", + "integrity": "sha512-4FF/5jNd86x9iSk/xQB1KRFWkhMWd/Z7x7tOwztgZYDj6aYR/3Xru7pb2BD6s6Oli/eeQaXTG11+eY9zdrJIQA==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -51,9 +51,9 @@ }, "dependencies": { "aws-cdk": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.88.0.tgz", - "integrity": "sha512-7Tj0uusA2nsEOsqkd4kB5vmzciz7l/eGBN5a+Ce4/CCcoe4ZCvT85L+T6tK0aohUTLZTAlTPBceH34RN5iMYpA==", + "version": "2.89.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.89.0.tgz", + "integrity": "sha512-4FF/5jNd86x9iSk/xQB1KRFWkhMWd/Z7x7tOwztgZYDj6aYR/3Xru7pb2BD6s6Oli/eeQaXTG11+eY9zdrJIQA==", "dev": true, "requires": { "fsevents": "2.3.2" diff --git a/package.json b/package.json index 396ea6c7921..2b7ef9dc54e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.88.0" + "aws-cdk": "^2.89.0" }, "dependencies": { "package-lock.json": "^1.0.0" From 88484426969bc7c02853b878564004c00f8f06bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:50:53 +0200 Subject: [PATCH 37/92] chore(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer (#2889) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 16 ++++++------- layer/scripts/layer-balancer/go.sum | 36 +++++++++++++---------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index bdc8a7f59ae..15941c60069 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.20.0 - github.com/aws/aws-sdk-go-v2/config v1.18.30 + github.com/aws/aws-sdk-go-v2/config v1.18.31 github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 @@ -12,15 +12,15 @@ require ( require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.29 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.30 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.14 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.20.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.13.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.21.0 // indirect github.com/aws/smithy-go v1.14.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index d32dd1c4350..abdad5f8003 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,33 +1,29 @@ -github.com/aws/aws-sdk-go-v2 v1.19.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.20.0 h1:INUDpYLt4oiPOJl0XwZDK2OVAVf0Rzo+MGVTv9f+gy8= github.com/aws/aws-sdk-go-v2 v1.20.0/go.mod h1:uWOr0m0jDsiWw8nnXiqZ+YG6LdvAlGYDLLf2NmHZoy4= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 h1:/MS8AzqYNAhhRNalOmxUvYs8VEbNGifTnzhPFdcRQkQ= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11/go.mod h1:va22++AdXht4ccO3kH2SHkHHYvZ2G9Utz+CXKmm2CaU= -github.com/aws/aws-sdk-go-v2/config v1.18.30 h1:TTAXQIn31qYFUQjkW6siVrRTX1ux+sADZDOe3jsZcMg= -github.com/aws/aws-sdk-go-v2/config v1.18.30/go.mod h1:+YogjT7e/t9JVu/sOnZZgxTge1G+bPNk8zOaI0QIQvE= -github.com/aws/aws-sdk-go-v2/credentials v1.13.29 h1:KNgCpThGuZyCjq9EuuqoLDenKKMwO/x1Xx01ckDa7VI= -github.com/aws/aws-sdk-go-v2/credentials v1.13.29/go.mod h1:VMq1LcmSEa9qxBlOCYTjVuGJWEEzhGmgL552jQsmhss= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6 h1:kortK122LvTU34CGX/F9oJpelXKkEA2j/MW48II+8+8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.6/go.mod h1:k7IPHyHNIASI0m0RwOmCjWOTtgG+J0raqwuHH8WhWJE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.36/go.mod h1:T8Jsn/uNL/AFOXrVYQ1YQaN1r9gN34JU1855/Lyjv+o= +github.com/aws/aws-sdk-go-v2/config v1.18.31 h1:CcacHsJjsPtHpe1MaopwPddUErmLnl+X77+7n4G2KkY= +github.com/aws/aws-sdk-go-v2/config v1.18.31/go.mod h1:pnSeuahFFvtScCHy0INXLxJ4N8H7KncD5u6A48bx3/8= +github.com/aws/aws-sdk-go-v2/credentials v1.13.30 h1:4pt4sI4OwXrrWUGuGr5NEb2g+4IBUB/I2BVj0t2Ak7Q= +github.com/aws/aws-sdk-go-v2/credentials v1.13.30/go.mod h1:Scpo/dGUdxAtRKsNCaXMXONnl3gvvugbXVldy5Fz2DQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 h1:X3H6+SU21x+76LRglk21dFRgMTJMa5QcpW+SqUf5BBg= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7/go.mod h1:3we0V09SwcJBzNlnyovrR2wWJhWmVdqAsmVs4uronv8= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 h1:zr/gxAZkMcvP71ZhQOcvdm8ReLjFgIXnIn0fw5AM7mo= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37/go.mod h1:Pdn4j43v49Kk6+82spO3Tu5gSeQXRsxo56ePPQAvFiA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.30/go.mod h1:v3GSCnFxbHzt9dlWBqvA1K1f9lmWuf4ztupZBCAIVs4= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 h1:0HCMIkAkVY9KMgueD8tf4bRTUanzEYvhw7KkPXIMpO0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31/go.mod h1:fTJDMe8LOFYtqiFFFeHA+SVMAwqLhoq0kcInYoLa9Js= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37 h1:BXiqvN7WuV/pMhz8CivhO8cG8icJcjnjHumif4ukQ0c= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.37/go.mod h1:d4GZ62cjnz/hjKFdAu11gAwK73bdhqaFv2O4J1gaqIs= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30 h1:UcVZxLVNY4yayCmiG94Ge3l2qbc5WEB/oa4RmjoQEi0= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.30/go.mod h1:wPffyJiWWtHwvpFyn23WjAjVjMnlQOQrl02+vutBh3Y= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 h1:+i1DOFrW3YZ3apE45tCal9+aDKK6kNEbW6Ib7e1nFxE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38/go.mod h1:1/jLp0OgOaWIetycOmycW+vYTYgTZFPttJQRgsI1PoU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31 h1:auGDJ0aLZahF5SPvkJ6WcUuX7iQ7kyl2MamV7Tm8QBk= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31/go.mod h1:3+lloe3sZuBQw1aBc5MyndvodzQlyqCZ7x1QPDHaWP4= github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0 h1:CDDjp86If1TkvURnNMWcYZpbG+WAGdfO7AWlrwWJ3dk= github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0/go.mod h1:MiY958jauOEVweMj4Xxa81B45wTg/6ewgp3XeCLV+hg= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.14 h1:gUjz7trfz9qBm0AlkKTvJHBXELi1wvw+2LA9GfD2AsM= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.14/go.mod h1:9kfRdJgLCbnyeqZ/DpaSwcgj9ZDYLfRpe8Sze+NrYfQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14 h1:8bEtxV5UT9ucdWGXfZ7CM3caQhSHGjWnTHt0OeF7m7s= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.14/go.mod h1:nd9BG2UnexN2sDx/mk2Jd6pf3d2E61AiA8m8Fdvdx8Y= -github.com/aws/aws-sdk-go-v2/service/sts v1.20.1 h1:U7h9CPoyMfVoN5jUglB0LglCMP10AK4vMBsbsCKM8Yw= -github.com/aws/aws-sdk-go-v2/service/sts v1.20.1/go.mod h1:BUHusg4cOA1TFGegj7x8/eoWrbdHzJfoMrXcbMQAG0k= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.0 h1:agnjK56/1jtGPehxV8QZ/AYHV++pEfl7CpYbWjHjBDc= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.0/go.mod h1:TC9BubuFMVScIU+TLKamO6VZiYTkYoEHqlSQwAe2omw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.0 h1:g0Rr6COTBEaIG9TFQ0GmRkPWOGuDfySGSq2PlMcclrY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.0/go.mod h1:XO/VcyoQ8nKyKfFW/3DMsRQXsfh/052tHTWmg3xBXRg= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.0 h1:HI1YIL5Q9FtucxF5tcNpzCEyLnkeUcqg6xtOx8u09S4= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.0/go.mod h1:G8SbvL0rFk4WOJroU8tKBczhsbhj2p/YY7qeJezJ3CI= github.com/aws/smithy-go v1.14.0 h1:+X90sB94fizKjDmwb4vyl2cTTPXTE5E2G/1mjByb0io= github.com/aws/smithy-go v1.14.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From fb42faad36ece52fd4be742159c2eb3e6b902b5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:15:33 +0200 Subject: [PATCH 38/92] chore(deps-dev): bump the boto-typing group with 11 updates (#2901) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 90 +++++++++++++++++++++++++------------------------- pyproject.toml | 22 ++++++------ 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/poetry.lock b/poetry.lock index b8521c3ca9c..ba1a06f0ad5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1431,13 +1431,13 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-appconfig" -version = "1.28.12" -description = "Type annotations for boto3.AppConfig 1.28.12 service generated with mypy-boto3-builder 7.15.2" +version = "1.28.16" +description = "Type annotations for boto3.AppConfig 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfig-1.28.12.tar.gz", hash = "sha256:02080219c25b7d7837257d070109ba1fe55cd281eb1f8115ca94556d25453e29"}, - {file = "mypy_boto3_appconfig-1.28.12-py3-none-any.whl", hash = "sha256:4796bdae21a86de03198c181e514875287b2cbac46a7718d25128cb61c457f0a"}, + {file = "mypy-boto3-appconfig-1.28.16.tar.gz", hash = "sha256:42354a56461db07ffb743066a1c008efa9804c378913051780a4aef583425556"}, + {file = "mypy_boto3_appconfig-1.28.16-py3-none-any.whl", hash = "sha256:12a6a4ab6a1fc30d7a24415506dcd69eae4742160286910242cefc15722ac532"}, ] [package.dependencies] @@ -1445,13 +1445,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-appconfigdata" -version = "1.28.15" -description = "Type annotations for boto3.AppConfigData 1.28.15 service generated with mypy-boto3-builder 7.16.1" +version = "1.28.16" +description = "Type annotations for boto3.AppConfigData 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-appconfigdata-1.28.15.tar.gz", hash = "sha256:ce6ee92c180c6fd7ac03dfd6a4502164c014b89c59a1e0f67aab88bc96895098"}, - {file = "mypy_boto3_appconfigdata-1.28.15-py3-none-any.whl", hash = "sha256:76f4a37fd0cfd9106496ddda39e198e75f139fb055d79aac582ed44e08c8b71b"}, + {file = "mypy-boto3-appconfigdata-1.28.16.tar.gz", hash = "sha256:4f736f907c3da1f63ce03d121dab4c0cd35f3875176db86d9ba87ee0907adcd9"}, + {file = "mypy_boto3_appconfigdata-1.28.16-py3-none-any.whl", hash = "sha256:68a26f891b94fe45894c8d7d9773faafa45d70dd2c5fe85085998673e6b0bbc4"}, ] [package.dependencies] @@ -1459,13 +1459,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudformation" -version = "1.28.12" -description = "Type annotations for boto3.CloudFormation 1.28.12 service generated with mypy-boto3-builder 7.15.2" +version = "1.28.16" +description = "Type annotations for boto3.CloudFormation 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.28.12.tar.gz", hash = "sha256:2a276c52a4907d5f0b111a5fd0d880b20d188905cd8b672cde5ac46363a8b3fa"}, - {file = "mypy_boto3_cloudformation-1.28.12-py3-none-any.whl", hash = "sha256:7b16b8a3000f9dff13ead9edcebd34ee19e2130d213ecf05b371e02048f1a7a3"}, + {file = "mypy-boto3-cloudformation-1.28.16.tar.gz", hash = "sha256:a5202db1ea76aa499a27b971745e0130e5cb88c2b323c48cca30cd01713d963a"}, + {file = "mypy_boto3_cloudformation-1.28.16-py3-none-any.whl", hash = "sha256:228cb6e9096f64d36abd912c34e465545ff848bb837498112dc30235ca19750c"}, ] [package.dependencies] @@ -1473,13 +1473,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudwatch" -version = "1.28.12" -description = "Type annotations for boto3.CloudWatch 1.28.12 service generated with mypy-boto3-builder 7.15.2" +version = "1.28.16" +description = "Type annotations for boto3.CloudWatch 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudwatch-1.28.12.tar.gz", hash = "sha256:c3205f75845a6b9aff313f2e74e1f5e4b7462772946da9c27cf0fa09194f83b9"}, - {file = "mypy_boto3_cloudwatch-1.28.12-py3-none-any.whl", hash = "sha256:d81da96bc035265a53a72ff813250ae19af12a404f24adb86fcc1376c42de441"}, + {file = "mypy-boto3-cloudwatch-1.28.16.tar.gz", hash = "sha256:15ccb83964bae8c15479852a9526898e6105defd6d09cc326034e98e4b00a896"}, + {file = "mypy_boto3_cloudwatch-1.28.16-py3-none-any.whl", hash = "sha256:fc3c5df0e67ac4b4bf246bcb06ab2ecb9ccff6a5fa1ced51dd2fd8e59a2863df"}, ] [package.dependencies] @@ -1487,13 +1487,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.28.11" -description = "Type annotations for boto3.DynamoDB 1.28.11 service generated with mypy-boto3-builder 7.15.1" +version = "1.28.16" +description = "Type annotations for boto3.DynamoDB 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.28.11.tar.gz", hash = "sha256:14b3fc0f091fad2c467733d410b1438b2747ab57292784abc0bc1adc3fa7ec60"}, - {file = "mypy_boto3_dynamodb-1.28.11-py3-none-any.whl", hash = "sha256:2b777cc080228e6c0e0b7a7e53b30d8c954637c7a5ec628f4397891f844ab0e8"}, + {file = "mypy-boto3-dynamodb-1.28.16.tar.gz", hash = "sha256:540fad881e240cb624b6e22b4461048c31cfb9ef1da6ae26ca70d1f385605930"}, + {file = "mypy_boto3_dynamodb-1.28.16-py3-none-any.whl", hash = "sha256:e9be4037aaad101689aae080fc3ca9ee8995a4d721235fc5d88aa005e3cf67c2"}, ] [package.dependencies] @@ -1501,13 +1501,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-lambda" -version = "1.28.15" -description = "Type annotations for boto3.Lambda 1.28.15 service generated with mypy-boto3-builder 7.16.1" +version = "1.28.16" +description = "Type annotations for boto3.Lambda 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.28.15.tar.gz", hash = "sha256:9f063ddf67be8b5d9d8bb5a6e072d7aff22eebfca25f2d8f7b9cf351e18d9937"}, - {file = "mypy_boto3_lambda-1.28.15-py3-none-any.whl", hash = "sha256:b189c948e41b86b80f84fe14f438c4cedfb81697039c4b1c01871a2aee3415a8"}, + {file = "mypy-boto3-lambda-1.28.16.tar.gz", hash = "sha256:c7c647139e6710da694aba4a644f69f4a06c6e43419168d69cc57f3dc6e5e607"}, + {file = "mypy_boto3_lambda-1.28.16-py3-none-any.whl", hash = "sha256:c1b688c1ea7cbb9b79b8a1dcaaa7459791ae7ebc608490251f58a07edb31170c"}, ] [package.dependencies] @@ -1515,13 +1515,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-logs" -version = "1.28.15" -description = "Type annotations for boto3.CloudWatchLogs 1.28.15 service generated with mypy-boto3-builder 7.16.1" +version = "1.28.16" +description = "Type annotations for boto3.CloudWatchLogs 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-logs-1.28.15.tar.gz", hash = "sha256:0208dbb873ad252258cc025e4598a14ef9ecae3623468cf8f82d3d7bcfafae7b"}, - {file = "mypy_boto3_logs-1.28.15-py3-none-any.whl", hash = "sha256:245cbf1ba6f2bdc8be1260d8991686eda5585f8c6c6c4b783c82b3568950e84c"}, + {file = "mypy-boto3-logs-1.28.16.tar.gz", hash = "sha256:2d6c613f17ecafff8d56ccdadc6642d1abdbd4674434a683ca8966304e201220"}, + {file = "mypy_boto3_logs-1.28.16-py3-none-any.whl", hash = "sha256:f8998bf7df00f712d507e6f4a830841e8b3806a865871dafdd03e4d06072e658"}, ] [package.dependencies] @@ -1529,13 +1529,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-s3" -version = "1.28.8" -description = "Type annotations for boto3.S3 1.28.8 service generated with mypy-boto3-builder 7.15.1" +version = "1.28.16" +description = "Type annotations for boto3.S3 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.28.8.tar.gz", hash = "sha256:c9ed17fee2c0e2edeb2966b3796af7b349dcc4eeee54dbd59a269fdb9418eb55"}, - {file = "mypy_boto3_s3-1.28.8-py3-none-any.whl", hash = "sha256:75b929c517c5ad8f97c14dfba5f8521db569157dc4ac76a07a178805777cff8c"}, + {file = "mypy-boto3-s3-1.28.16.tar.gz", hash = "sha256:4e55fdad729b6e6f45211e354bd1a0a745a565fe9d1e462737f775c28849cfb5"}, + {file = "mypy_boto3_s3-1.28.16-py3-none-any.whl", hash = "sha256:855f7848186c45adbd3c474fec2d75db17f4cd7200c0a2235473250454ec4686"}, ] [package.dependencies] @@ -1543,13 +1543,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-secretsmanager" -version = "1.28.3.post2" -description = "Type annotations for boto3.SecretsManager 1.28.3 service generated with mypy-boto3-builder 7.15.0" +version = "1.28.16" +description = "Type annotations for boto3.SecretsManager 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-secretsmanager-1.28.3.post2.tar.gz", hash = "sha256:f359f6446ac856d0887e40cb0f5bc6e0a60873524be5dd4b68be1d0fc4ac513e"}, - {file = "mypy_boto3_secretsmanager-1.28.3.post2-py3-none-any.whl", hash = "sha256:3a5e5619ee945f244d2dfefcb382c85874171a18b46f75403465622095284d25"}, + {file = "mypy-boto3-secretsmanager-1.28.16.tar.gz", hash = "sha256:07f443b31d2114ac363cfbdbc5f4b97934ca48fb99734bbd06d5c39bce244b83"}, + {file = "mypy_boto3_secretsmanager-1.28.16-py3-none-any.whl", hash = "sha256:05508c3a96d96e482e5aff21b508319a1911e6662aea5be96aa7f7089b8dbfd4"}, ] [package.dependencies] @@ -1557,13 +1557,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-ssm" -version = "1.28.12" -description = "Type annotations for boto3.SSM 1.28.12 service generated with mypy-boto3-builder 7.15.2" +version = "1.28.16" +description = "Type annotations for boto3.SSM 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-ssm-1.28.12.tar.gz", hash = "sha256:78b4cef65e18ae6714022d95955a51208a1614ca2dc6757735c9527c96cd7c14"}, - {file = "mypy_boto3_ssm-1.28.12-py3-none-any.whl", hash = "sha256:5576d651129cdef275f2dcf7d20dd6df17e45d1534e5020e7a1aac32227215d8"}, + {file = "mypy-boto3-ssm-1.28.16.tar.gz", hash = "sha256:736d11cb8def9a7c7206cbd64ff6b81fc3e74acb02b63985418937a0d2758d88"}, + {file = "mypy_boto3_ssm-1.28.16-py3-none-any.whl", hash = "sha256:75d94def8b8752bc84705d967d7fa25427ba5dbe3a5efc08e0579b4b074246f7"}, ] [package.dependencies] @@ -1571,13 +1571,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-xray" -version = "1.28.15" -description = "Type annotations for boto3.XRay 1.28.15 service generated with mypy-boto3-builder 7.16.1" +version = "1.28.16" +description = "Type annotations for boto3.XRay 1.28.16 service generated with mypy-boto3-builder 7.17.1" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-xray-1.28.15.tar.gz", hash = "sha256:ace907f4637a3a65b7645b8813599436940d31bd72ea61f9cd24ccf608a43f0e"}, - {file = "mypy_boto3_xray-1.28.15-py3-none-any.whl", hash = "sha256:6b5fde53dc8d93b04190792466bc122c83acb8534ce83e3eafdc5d9af1d632af"}, + {file = "mypy-boto3-xray-1.28.16.tar.gz", hash = "sha256:6ddd4acccf272bf663522c5fcd31b9b7dacbed4a01c91e44e4e8c0abb2343c0a"}, + {file = "mypy_boto3_xray-1.28.16-py3-none-any.whl", hash = "sha256:4bc7dfd46cb71ca6a9d46b47453d59a08ac80c872cc429dacb45a93abd737172"}, ] [package.dependencies] @@ -2695,4 +2695,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "03df7cb4d0cb94d716ed188bec7269a14e5b750fddbfbe38c0fd9f768ca1eb37" +content-hash = "f8d0d936c7109fd7e6e1049bbc454fea6cb4f9363fbff3acfe7edcf0117cae80" diff --git a/pyproject.toml b/pyproject.toml index bf03ce84bd6..e129d32a928 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,22 +56,22 @@ aws-cdk-lib = "^2.88.0" "aws-cdk.aws-apigatewayv2-integrations-alpha" = "^2.38.1-alpha.0" "aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" -mypy-boto3-appconfig = "^1.28.12" -mypy-boto3-cloudformation = "^1.28.12" -mypy-boto3-cloudwatch = "^1.28.12" -mypy-boto3-dynamodb = "^1.28.11" -mypy-boto3-lambda = "^1.28.15" -mypy-boto3-logs = "^1.28.15" -mypy-boto3-secretsmanager = "^1.28.3" -mypy-boto3-ssm = "^1.28.12" -mypy-boto3-s3 = "^1.28.8" -mypy-boto3-xray = "^1.28.15" +mypy-boto3-appconfig = "^1.28.16" +mypy-boto3-cloudformation = "^1.28.16" +mypy-boto3-cloudwatch = "^1.28.16" +mypy-boto3-dynamodb = "^1.28.16" +mypy-boto3-lambda = "^1.28.16" +mypy-boto3-logs = "^1.28.16" +mypy-boto3-secretsmanager = "^1.28.16" +mypy-boto3-ssm = "^1.28.16" +mypy-boto3-s3 = "^1.28.16" +mypy-boto3-xray = "^1.28.16" types-requests = "^2.31.0" typing-extensions = "^4.6.2" mkdocs-material = "^9.1.21" filelock = "^3.12.2" checksumdir = "^1.2.0" -mypy-boto3-appconfigdata = "^1.28.15" +mypy-boto3-appconfigdata = "^1.28.16" ijson = "^3.2.2" typed-ast = { version = "^1.5.5", python = "< 3.8"} hvac = "^1.1.1" From c06b866bb22f9e143f42fa65f8a13cb9bf7805cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:24:30 +0200 Subject: [PATCH 39/92] chore(deps-dev): bump cfn-lint from 0.79.5 to 0.79.6 (#2899) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index ba1a06f0ad5..b8cffe841df 100644 --- a/poetry.lock +++ b/poetry.lock @@ -365,13 +365,13 @@ files = [ [[package]] name = "cfn-lint" -version = "0.79.5" +version = "0.79.6" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "cfn-lint-0.79.5.tar.gz", hash = "sha256:7a00dba8f70b8a92c38bfc8f45e2ab20cedad5c49054a46f1ce931e48fc1cd0c"}, - {file = "cfn_lint-0.79.5-py3-none-any.whl", hash = "sha256:3054a2e407f77b3115c41de49fe2c11d728d53ab7be4ae478c1b5ff0e21331b7"}, + {file = "cfn-lint-0.79.6.tar.gz", hash = "sha256:09fc9cc497fc6d15e8b822a98fa0628ed6f8e9bcce6c289d95b2fc71d50aa63f"}, + {file = "cfn_lint-0.79.6-py3-none-any.whl", hash = "sha256:b67154460acb466e837590caa7a76bd95ec908961f21ba6de2d985309668ea29"}, ] [package.dependencies] @@ -2695,4 +2695,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "f8d0d936c7109fd7e6e1049bbc454fea6cb4f9363fbff3acfe7edcf0117cae80" +content-hash = "c2b1618c7fec5dc255f770086d997ff439344805f5d3fec681304595e16a7a1b" diff --git a/pyproject.toml b/pyproject.toml index e129d32a928..1a655adaf07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,7 +86,7 @@ all = ["pydantic", "aws-xray-sdk", "fastjsonschema"] aws-sdk = ["boto3"] [tool.poetry.group.dev.dependencies] -cfn-lint = "0.79.5" +cfn-lint = "0.79.6" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" From b2139aa7c641204825b56f91702bcaf28a715d2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:36:42 +0200 Subject: [PATCH 40/92] chore(deps-dev): bump sentry-sdk from 1.28.1 to 1.29.0 (#2900) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index b8cffe841df..99959fd90c5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2276,13 +2276,13 @@ pbr = "*" [[package]] name = "sentry-sdk" -version = "1.28.1" +version = "1.29.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.28.1.tar.gz", hash = "sha256:dcd88c68aa64dae715311b5ede6502fd684f70d00a7cd4858118f0ba3153a3ae"}, - {file = "sentry_sdk-1.28.1-py2.py3-none-any.whl", hash = "sha256:6bdb25bd9092478d3a817cb0d01fa99e296aea34d404eac3ca0037faa5c2aa0a"}, + {file = "sentry-sdk-1.29.0.tar.gz", hash = "sha256:5053aa7647533b207417cea5f3ee2d5e13aea7001dbb711f46348d7a72597d60"}, + {file = "sentry_sdk-1.29.0-py2.py3-none-any.whl", hash = "sha256:78c764cbec1967c41e24967e9a4a5d1e67a7bc960d125d905f94c068a0300ac9"}, ] [package.dependencies] From 0916bc5c4935143c27e8bfa9f1b761786a081483 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:03:55 -0300 Subject: [PATCH 41/92] chore(deps-dev): bump ruff from 0.0.280 to 0.0.281 (#2891) * chore(deps-dev): bump ruff from 0.0.280 to 0.0.281 Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.280 to 0.0.281. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.0.280...v0.0.281) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Fixing NOQA Signed-off-by: Cavalcante Damascena --------- Signed-off-by: dependabot[bot] Signed-off-by: Cavalcante Damascena Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Cavalcante Damascena --- .../parser/models/s3_object_event.py | 2 +- poetry.lock | 38 +++++++++---------- pyproject.toml | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/aws_lambda_powertools/utilities/parser/models/s3_object_event.py b/aws_lambda_powertools/utilities/parser/models/s3_object_event.py index 7ef98fe4bb2..867cd996fa0 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3_object_event.py +++ b/aws_lambda_powertools/utilities/parser/models/s3_object_event.py @@ -39,7 +39,7 @@ class S3ObjectSessionContext(BaseModel): class S3ObjectUserIdentity(BaseModel): - type: str # noqa003 + type: str # noqa: A003 accountId: str accessKeyId: str userName: Optional[str] = None diff --git a/poetry.lock b/poetry.lock index 99959fd90c5..3fcd22c4a4f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2218,28 +2218,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.280" +version = "0.0.281" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.280-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:48ed5aca381050a4e2f6d232db912d2e4e98e61648b513c350990c351125aaec"}, - {file = "ruff-0.0.280-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ef6ee3e429fd29d6a5ceed295809e376e6ece5b0f13c7e703efaf3d3bcb30b96"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d878370f7e9463ac40c253724229314ff6ebe4508cdb96cb536e1af4d5a9cd4f"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83e8f372fa5627eeda5b83b5a9632d2f9c88fc6d78cead7e2a1f6fb05728d137"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7008fc6ca1df18b21fa98bdcfc711dad5f94d0fc3c11791f65e460c48ef27c82"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe7118c1eae3fda17ceb409629c7f3b5a22dffa7caf1f6796776936dca1fe653"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:37359cd67d2af8e09110a546507c302cbea11c66a52d2a9b6d841d465f9962d4"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd58af46b0221efb95966f1f0f7576df711cb53e50d2fdb0e83c2f33360116a4"}, - {file = "ruff-0.0.280-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e7c15828d09f90e97bea8feefcd2907e8c8ce3a1f959c99f9b4b3469679f33c"}, - {file = "ruff-0.0.280-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2dae8f2d9c44c5c49af01733c2f7956f808db682a4193180dedb29dd718d7bbe"}, - {file = "ruff-0.0.280-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5f972567163a20fb8c2d6afc60c2ea5ef8b68d69505760a8bd0377de8984b4f6"}, - {file = "ruff-0.0.280-py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ffa7347ad11643f29de100977c055e47c988cd6d9f5f5ff83027600b11b9189"}, - {file = "ruff-0.0.280-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7a37dab70114671d273f203268f6c3366c035fe0c8056614069e90a65e614bfc"}, - {file = "ruff-0.0.280-py3-none-win32.whl", hash = "sha256:7784e3606352fcfb193f3cd22b2e2117c444cb879ef6609ec69deabd662b0763"}, - {file = "ruff-0.0.280-py3-none-win_amd64.whl", hash = "sha256:4a7d52457b5dfcd3ab24b0b38eefaead8e2dca62b4fbf10de4cd0938cf20ce30"}, - {file = "ruff-0.0.280-py3-none-win_arm64.whl", hash = "sha256:b7de5b8689575918e130e4384ed9f539ce91d067c0a332aedef6ca7188adac2d"}, - {file = "ruff-0.0.280.tar.gz", hash = "sha256:581c43e4ac5e5a7117ad7da2120d960a4a99e68ec4021ec3cd47fe1cf78f8380"}, + {file = "ruff-0.0.281-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:418fbddfd3dba4d7b11e4e016eacc40d321ff0b7d3637c7ba9ad3ee0474c9a35"}, + {file = "ruff-0.0.281-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c086bf3968d5cb2b4f31a586fc73bc42cb688c32f4c992ff161d4ce19f551cf2"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0162b149a94f6007768820bcdf4ccb7e90a21655aac829ace49f4682d0565fdb"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3495175e6d85a01d3da409a079461a5a3c15b70237cc82550ad8c1f091002c8"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae0b836c03a7010527bb56384a4e3718e0958e32bea64459879aacdcb65c4945"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6d34cae6ef6c6b6fd6d4f09271fbf635db49e6b788da1b2e1dea11a29f1c2a11"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd3c94260a148e955fb46f41d4bcecd857c75794e9f06ebfa7f9be65cfed9621"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ccb875a4000bcba6cc61cb9d3cd5969d6b0921b5234f0ef99ad75f74e8935ef"}, + {file = "ruff-0.0.281-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f5b8ccaabad61e2d50494df820b7bafd94eac13f10d2d8b831994c1618801a9"}, + {file = "ruff-0.0.281-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:cbf279fd9c2ca674896656df2d82831010afd336a6703a060fe08d6f2358e47b"}, + {file = "ruff-0.0.281-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:24d0defeb2c6a1b16a4230840d1138e08bc4ef2318496fa6ff7ddbf3a443626f"}, + {file = "ruff-0.0.281-py3-none-musllinux_1_2_i686.whl", hash = "sha256:54bab7128167057ee5987bbd9f925fbf105071068de9d8474ca7c38f684b8463"}, + {file = "ruff-0.0.281-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:29a22b7a6433ce0b4e601897e8a5dd58a75c75c01afee9b8922ebbdd1fe51e51"}, + {file = "ruff-0.0.281-py3-none-win32.whl", hash = "sha256:7b781f6a7ed35196e6565ed32f57d07b852b0dcd7158c6c7669c8b5d0f8cf97a"}, + {file = "ruff-0.0.281-py3-none-win_amd64.whl", hash = "sha256:70f921438bf09f04c0547cf64c137c87ef33cbec2b64be12b8caa87df261a016"}, + {file = "ruff-0.0.281-py3-none-win_arm64.whl", hash = "sha256:42a92a62fc841f7444821444553fd6e1e700bb55348f24e8ec39afdd4e3d0312"}, + {file = "ruff-0.0.281.tar.gz", hash = "sha256:bab2cdfa78754315cccc2b4d46ad6181aabb29e89747a3b135a4b85e11baa025"}, ] [[package]] @@ -2695,4 +2695,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "c2b1618c7fec5dc255f770086d997ff439344805f5d3fec681304595e16a7a1b" +content-hash = "e634f248e2f28160fd669018c4be9cc25b639f6a9c75c5c000386a19acff67db" diff --git a/pyproject.toml b/pyproject.toml index 1a655adaf07..2ec9d8f81f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.281" +ruff = ">=0.0.272,<0.0.282" retry2 = "^0.9.5" [tool.coverage.run] From cdf90845e9841193364cbc2e066554d5e6da09d4 Mon Sep 17 00:00:00 2001 From: Roger Zhang Date: Tue, 1 Aug 2023 10:04:21 -0700 Subject: [PATCH 42/92] feat(metrics): support to bring your own metrics provider (#2194) * Use a different Metric class for different provider * fix static checking error * fix static checking error * optimize docstring * add alias CloudWatchEMF to original Metrics class * add alias CloudWatchEMF to original Metrics class * Move Metrics to Provider * add sample document * reformat code block * add OTel provider draft for poc * rebasing from upstream * rebasing from upstream * add test to metrics providers * docstring + code coverage * python annotations + imports * fix docstring polish datadog_provider add flush_to_log parameter remove OTEL provider draft * add tests for datadog provider * add tests for datadog provider * migrate from ABC to protocol, support convert kwargs to tags, add test * migrate from ABC to protocol, support convert kwargs to tags, add test * migrate from ABC to protocol, support convert kwargs to tags, add test * remove parent class, fix example * base: fix small problems * refactoring: removing Datadog provider * refactoring: importing from typing_extensions * refactoring EMF provider * refactoring cloudwatchemf provider and cleaning code * fix mypy error * fix mypy error * fix metric tests * fix documentation * adding test --------- Signed-off-by: Leandro Damascena Co-authored-by: Leandro Damascena Co-authored-by: Leandro Damascena Co-authored-by: Cavalcante Damascena --- .gitleaks.toml | 15 + aws_lambda_powertools/metrics/__init__.py | 15 +- aws_lambda_powertools/metrics/base.py | 99 ++-- aws_lambda_powertools/metrics/exceptions.py | 14 +- aws_lambda_powertools/metrics/metric.py | 2 +- aws_lambda_powertools/metrics/metrics.py | 262 ++++++--- .../metrics/provider/__init__.py | 6 + .../metrics/provider/base.py | 244 +++++++++ .../provider/cloudwatch_emf/__init__.py | 0 .../provider/cloudwatch_emf/cloudwatch.py | 496 ++++++++++++++++++ .../provider/cloudwatch_emf/cold_start.py | 9 + .../provider/cloudwatch_emf/constants.py | 2 + .../provider/cloudwatch_emf/exceptions.py | 10 + .../cloudwatch_emf/metric_properties.py | 37 ++ docs/maintainers.md | 1 + poetry.lock | 97 ++-- ruff.toml | 2 + tests/functional/test_metrics.py | 212 +++++++- 18 files changed, 1317 insertions(+), 206 deletions(-) create mode 100644 .gitleaks.toml create mode 100644 aws_lambda_powertools/metrics/provider/__init__.py create mode 100644 aws_lambda_powertools/metrics/provider/base.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/__init__.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/cold_start.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 00000000000..0622b57c118 --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,15 @@ +# Title for the gitleaks configuration file. +title = "Gitleaks" + +[extend] +# useDefault will extend the base configuration with the default gitleaks config: +# https://github.com/zricethezav/gitleaks/blob/master/config/gitleaks.toml +useDefault = true + +[allowlist] +description = "Allow list false positive" + +# Allow list paths to ignore due to false positives. +paths = [ + '''tests/unit/parser/test_kinesis_firehose\.py''', +] diff --git a/aws_lambda_powertools/metrics/__init__.py b/aws_lambda_powertools/metrics/__init__.py index 5f30f14102d..b8c94478816 100644 --- a/aws_lambda_powertools/metrics/__init__.py +++ b/aws_lambda_powertools/metrics/__init__.py @@ -1,23 +1,22 @@ """CloudWatch Embedded Metric Format utility """ -from .base import MetricResolution, MetricUnit -from .exceptions import ( +from aws_lambda_powertools.metrics.base import MetricResolution, MetricUnit, single_metric +from aws_lambda_powertools.metrics.exceptions import ( MetricResolutionError, MetricUnitError, MetricValueError, SchemaValidationError, ) -from .metric import single_metric -from .metrics import EphemeralMetrics, Metrics +from aws_lambda_powertools.metrics.metrics import EphemeralMetrics, Metrics __all__ = [ - "Metrics", - "EphemeralMetrics", "single_metric", - "MetricUnit", "MetricUnitError", - "MetricResolution", "MetricResolutionError", "SchemaValidationError", "MetricValueError", + "Metrics", + "EphemeralMetrics", + "MetricResolution", + "MetricUnit", ] diff --git a/aws_lambda_powertools/metrics/base.py b/aws_lambda_powertools/metrics/base.py index 6a5e7282392..b32421431cd 100644 --- a/aws_lambda_powertools/metrics/base.py +++ b/aws_lambda_powertools/metrics/base.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime import functools import json @@ -7,59 +9,28 @@ import warnings from collections import defaultdict from contextlib import contextmanager -from enum import Enum from typing import Any, Callable, Dict, Generator, List, Optional, Union -from ..shared import constants -from ..shared.functions import resolve_env_var_choice -from .exceptions import ( +from aws_lambda_powertools.metrics.exceptions import ( MetricResolutionError, MetricUnitError, MetricValueError, SchemaValidationError, ) -from .types import MetricNameUnitResolution +from aws_lambda_powertools.metrics.provider.cloudwatch_emf import cold_start +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cold_start import ( + reset_cold_start_flag, # noqa: F401 # backwards compatibility +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit +from aws_lambda_powertools.metrics.types import MetricNameUnitResolution +from aws_lambda_powertools.shared import constants +from aws_lambda_powertools.shared.functions import resolve_env_var_choice logger = logging.getLogger(__name__) -MAX_METRICS = 100 -MAX_DIMENSIONS = 29 - -is_cold_start = True - - -class MetricResolution(Enum): - Standard = 60 - High = 1 - - -class MetricUnit(Enum): - 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" - BytesPerSecond = "Bytes/Second" - KilobytesPerSecond = "Kilobytes/Second" - MegabytesPerSecond = "Megabytes/Second" - GigabytesPerSecond = "Gigabytes/Second" - TerabytesPerSecond = "Terabytes/Second" - BitsPerSecond = "Bits/Second" - KilobitsPerSecond = "Kilobits/Second" - MegabitsPerSecond = "Megabits/Second" - GigabitsPerSecond = "Gigabits/Second" - TerabitsPerSecond = "Terabits/Second" - CountPerSecond = "Count/Second" +# Maintenance: alias due to Hyrum's law +is_cold_start = cold_start.is_cold_start class MetricManager: @@ -94,11 +65,11 @@ class MetricManager: def __init__( self, - metric_set: Optional[Dict[str, Any]] = None, - dimension_set: Optional[Dict] = None, - namespace: Optional[str] = None, - metadata_set: Optional[Dict[str, Any]] = None, - service: Optional[str] = None, + metric_set: Dict[str, Any] | None = None, + dimension_set: Dict | None = None, + namespace: str | None = None, + metadata_set: Dict[str, Any] | None = None, + service: str | None = None, ): self.metric_set = metric_set if metric_set is not None else {} self.dimension_set = dimension_set if dimension_set is not None else {} @@ -112,9 +83,9 @@ def __init__( def add_metric( self, name: str, - unit: Union[MetricUnit, str], + unit: MetricUnit | str, value: float, - resolution: Union[MetricResolution, int] = 60, + resolution: MetricResolution | int = 60, ) -> None: """Adds given metric @@ -173,9 +144,9 @@ def add_metric( def serialize_metric_set( self, - metrics: Optional[Dict] = None, - dimensions: Optional[Dict] = None, - metadata: Optional[Dict] = None, + metrics: Dict | None = None, + dimensions: Dict | None = None, + metadata: Dict | None = None, ) -> Dict: """Serializes metric and dimensions set @@ -355,10 +326,10 @@ def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: def log_metrics( self, - lambda_handler: Union[Callable[[Dict, Any], Any], Optional[Callable[[Dict, Any, Optional[Dict]], Any]]] = None, + lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, capture_cold_start_metric: bool = False, raise_on_empty_metrics: bool = False, - default_dimensions: Optional[Dict[str, str]] = None, + default_dimensions: Dict[str, str] | None = None, ): """Decorator to serialize and publish metrics at the end of a function execution. @@ -537,9 +508,9 @@ class SingleMetric(MetricManager): def add_metric( self, name: str, - unit: Union[MetricUnit, str], + unit: MetricUnit | str, value: float, - resolution: Union[MetricResolution, int] = 60, + resolution: MetricResolution | int = 60, ) -> None: """Method to prevent more than one metric being created @@ -565,9 +536,9 @@ def single_metric( name: str, unit: MetricUnit, value: float, - resolution: Union[MetricResolution, int] = 60, - namespace: Optional[str] = None, - default_dimensions: Optional[Dict[str, str]] = None, + resolution: MetricResolution | int = 60, + namespace: str | None = None, + default_dimensions: Dict[str, str] | None = None, ) -> Generator[SingleMetric, None, None]: """Context manager to simplify creation of a single metric @@ -622,7 +593,7 @@ def single_metric( SchemaValidationError When metric object fails EMF schema validation """ # noqa: E501 - metric_set: Optional[Dict] = None + metric_set: Dict | None = None try: metric: SingleMetric = SingleMetric(namespace=namespace) metric.add_metric(name=name, unit=unit, value=value, resolution=resolution) @@ -635,9 +606,3 @@ def single_metric( metric_set = metric.serialize_metric_set() finally: print(json.dumps(metric_set, separators=(",", ":"))) - - -def reset_cold_start_flag(): - global is_cold_start - if not is_cold_start: - is_cold_start = True diff --git a/aws_lambda_powertools/metrics/exceptions.py b/aws_lambda_powertools/metrics/exceptions.py index 94f492d14d7..30a4996d67e 100644 --- a/aws_lambda_powertools/metrics/exceptions.py +++ b/aws_lambda_powertools/metrics/exceptions.py @@ -1,13 +1,4 @@ -class MetricUnitError(Exception): - """When metric unit is not supported by CloudWatch""" - - pass - - -class MetricResolutionError(Exception): - """When metric resolution is not supported by CloudWatch""" - - pass +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricResolutionError, MetricUnitError class SchemaValidationError(Exception): @@ -20,3 +11,6 @@ class MetricValueError(Exception): """When metric value isn't a valid number""" pass + + +__all__ = ["MetricUnitError", "MetricResolutionError", "SchemaValidationError", "MetricValueError"] diff --git a/aws_lambda_powertools/metrics/metric.py b/aws_lambda_powertools/metrics/metric.py index 5465889f1f0..e2ac49df489 100644 --- a/aws_lambda_powertools/metrics/metric.py +++ b/aws_lambda_powertools/metrics/metric.py @@ -1,4 +1,4 @@ # NOTE: prevents circular inheritance import -from .base import SingleMetric, single_metric +from aws_lambda_powertools.metrics.base import SingleMetric, single_metric __all__ = ["SingleMetric", "single_metric"] diff --git a/aws_lambda_powertools/metrics/metrics.py b/aws_lambda_powertools/metrics/metrics.py index 487f2ab9b2f..d87b7bdd401 100644 --- a/aws_lambda_powertools/metrics/metrics.py +++ b/aws_lambda_powertools/metrics/metrics.py @@ -1,9 +1,13 @@ -from typing import Any, Dict, Optional +# NOTE: keeps for compatibility +from __future__ import annotations -from .base import MetricManager +from typing import Any, Callable, Dict, Optional, Union +from aws_lambda_powertools.metrics.base import MetricResolution, MetricUnit +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import AmazonCloudWatchEMFProvider -class Metrics(MetricManager): + +class Metrics: """Metrics create an EMF object with up to 100 metrics Use Metrics when you need to create multiple metrics that have @@ -69,76 +73,82 @@ def lambda_handler(): _metadata: Dict[str, Any] = {} _default_dimensions: Dict[str, Any] = {} - def __init__(self, service: Optional[str] = None, namespace: Optional[str] = None): + def __init__( + self, + service: str | None = None, + namespace: str | None = None, + provider: AmazonCloudWatchEMFProvider | None = None, + ): self.metric_set = self._metrics self.metadata_set = self._metadata self.default_dimensions = self._default_dimensions self.dimension_set = self._dimensions self.dimension_set.update(**self._default_dimensions) - super().__init__( - namespace=namespace, - service=service, - metric_set=self.metric_set, - dimension_set=self.dimension_set, - metadata_set=self.metadata_set, - ) - - def set_default_dimensions(self, **dimensions) -> None: - """Persist dimensions across Lambda invocations - - Parameters - ---------- - dimensions : Dict[str, Any], optional - metric dimensions as key=value - - Example - ------- - **Sets some default dimensions that will always be present across metrics and invocations** - from aws_lambda_powertools import Metrics - - metrics = Metrics(namespace="ServerlessAirline", service="payment") - metrics.set_default_dimensions(environment="demo", another="one") - - @metrics.log_metrics() - def lambda_handler(): - return True - """ - for name, value in dimensions.items(): - self.add_dimension(name, value) - - self.default_dimensions.update(**dimensions) - - def clear_default_dimensions(self) -> None: - self.default_dimensions.clear() - - def clear_metrics(self) -> None: - super().clear_metrics() - # re-add default dimensions - self.set_default_dimensions(**self.default_dimensions) - - -class EphemeralMetrics(MetricManager): - """Non-singleton version of Metrics to not persist metrics across instances - - NOTE: This is useful when you want to: - - - Create metrics for distinct namespaces - - Create the same metrics with different dimensions more than once - """ + if provider is None: + self.provider = AmazonCloudWatchEMFProvider( + namespace=namespace, + service=service, + metric_set=self.metric_set, + dimension_set=self.dimension_set, + metadata_set=self.metadata_set, + default_dimensions=self._default_dimensions, + ) + else: + self.provider = provider + + def add_metric( + self, + name: str, + unit: MetricUnit | str, + value: float, + resolution: MetricResolution | int = 60, + ) -> None: + self.provider.add_metric(name=name, unit=unit, value=value, resolution=resolution) + + def add_dimension(self, name: str, value: str) -> None: + self.provider.add_dimension(name=name, value=value) + + def serialize_metric_set( + self, + metrics: Dict | None = None, + dimensions: Dict | None = None, + metadata: Dict | None = None, + ) -> Dict: + return self.provider.serialize_metric_set(metrics=metrics, dimensions=dimensions, metadata=metadata) + + def add_metadata(self, key: str, value: Any) -> None: + self.provider.add_metadata(key=key, value=value) + + def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: + self.provider.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) + + def log_metrics( + self, + lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, + capture_cold_start_metric: bool = False, + raise_on_empty_metrics: bool = False, + default_dimensions: Dict[str, str] | None = None, + ): + return self.provider.log_metrics( + lambda_handler=lambda_handler, + capture_cold_start_metric=capture_cold_start_metric, + raise_on_empty_metrics=raise_on_empty_metrics, + default_dimensions=default_dimensions, + ) - _dimensions: Dict[str, str] = {} - _default_dimensions: Dict[str, Any] = {} + def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int: + return self.provider._extract_metric_resolution_value(resolution=resolution) - def __init__(self, service: Optional[str] = None, namespace: Optional[str] = None): - self.default_dimensions = self._default_dimensions - self.dimension_set = self._dimensions + def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: + return self.provider._extract_metric_unit_value(unit=unit) - self.dimension_set.update(**self._default_dimensions) - super().__init__(namespace=namespace, service=service) + def _add_cold_start_metric(self, context: Any) -> None: + self.provider._add_cold_start_metric(context=context) def set_default_dimensions(self, **dimensions) -> None: + self.provider.set_default_dimensions(**dimensions) """Persist dimensions across Lambda invocations Parameters @@ -165,9 +175,133 @@ def lambda_handler(): self.default_dimensions.update(**dimensions) def clear_default_dimensions(self) -> None: + self.provider.default_dimensions.clear() self.default_dimensions.clear() def clear_metrics(self) -> None: - super().clear_metrics() - # re-add default dimensions - self.set_default_dimensions(**self.default_dimensions) + self.provider.clear_metrics() + + +# Maintenance: until v3, we can't afford to break customers. +# AmazonCloudWatchEMFProvider has the exact same functionality (non-singleton) +# so we simply alias. If a customer subclassed `EphemeralMetrics` and somehow relied on __name__ +# we can quickly revert and duplicate code while using self.provider + +EphemeralMetrics = AmazonCloudWatchEMFProvider + +# noqa: ERA001 +# class EphemeralMetrics(MetricManager): +# """Non-singleton version of Metrics to not persist metrics across instances +# +# NOTE: This is useful when you want to: +# +# - Create metrics for distinct namespaces +# - Create the same metrics with different dimensions more than once +# """ +# +# # _dimensions: Dict[str, str] = {} +# _default_dimensions: Dict[str, Any] = {} +# +# def __init__( +# self, +# service: str | None = None, +# namespace: str | None = None, +# provider: AmazonCloudWatchEMFProvider | None = None, +# ): +# super().__init__(namespace=namespace, service=service) +# +# self.default_dimensions = self._default_dimensions +# # # self.dimension_set = self._dimensions +# # self.dimension_set.update(**self._default_dimensions) +# +# self.provider = provider or AmazonCloudWatchEMFProvider( +# namespace=namespace, +# service=service, +# metric_set=self.metric_set, +# metadata_set=self.metadata_set, +# dimension_set=self.dimension_set, +# default_dimensions=self._default_dimensions, +# ) +# +# def add_metric( +# self, +# name: str, +# unit: MetricUnit | str, +# value: float, +# resolution: MetricResolution | int = 60, +# ) -> None: +# return self.provider.add_metric(name=name, unit=unit, value=value, resolution=resolution) +# +# def add_dimension(self, name: str, value: str) -> None: +# return self.provider.add_dimension(name=name, value=value) +# +# def serialize_metric_set( +# self, +# metrics: Dict | None = None, +# dimensions: Dict | None = None, +# metadata: Dict | None = None, +# ) -> Dict: +# return self.provider.serialize_metric_set(metrics=metrics, dimensions=dimensions, metadata=metadata) +# +# def add_metadata(self, key: str, value: Any) -> None: +# self.provider.add_metadata(key=key, value=value) +# +# def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: +# self.provider.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) +# +# def log_metrics( +# self, +# lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, +# capture_cold_start_metric: bool = False, +# raise_on_empty_metrics: bool = False, +# default_dimensions: Dict[str, str] | None = None, +# ): +# return self.provider.log_metrics( +# lambda_handler=lambda_handler, +# capture_cold_start_metric=capture_cold_start_metric, +# raise_on_empty_metrics=raise_on_empty_metrics, +# default_dimensions=default_dimensions, +# ) +# +# def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int: +# return self.provider._extract_metric_resolution_value(resolution=resolution) +# +# def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: +# return self.provider._extract_metric_unit_value(unit=unit) +# +# def _add_cold_start_metric(self, context: Any) -> None: +# return self.provider._add_cold_start_metric(context=context) +# +# def set_default_dimensions(self, **dimensions) -> None: +# """Persist dimensions across Lambda invocations +# +# Parameters +# ---------- +# dimensions : Dict[str, Any], optional +# metric dimensions as key=value +# +# Example +# ------- +# **Sets some default dimensions that will always be present across metrics and invocations** +# +# from aws_lambda_powertools import Metrics +# +# metrics = Metrics(namespace="ServerlessAirline", service="payment") +# metrics.set_default_dimensions(environment="demo", another="one") +# +# @metrics.log_metrics() +# def lambda_handler(): +# return True +# """ +# return self.provider.set_default_dimensions(**dimensions) +# +# def clear_default_dimensions(self) -> None: +# self.default_dimensions.clear() +# +# def clear_metrics(self) -> None: +# self.provider.clear_metrics() +# # re-add default dimensions +# self.set_default_dimensions(**self.default_dimensions) +# + +# __all__ = [] diff --git a/aws_lambda_powertools/metrics/provider/__init__.py b/aws_lambda_powertools/metrics/provider/__init__.py new file mode 100644 index 00000000000..814812c135b --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/__init__.py @@ -0,0 +1,6 @@ +from aws_lambda_powertools.metrics.provider.base import MetricsBase, MetricsProviderBase + +__all__ = [ + "MetricsBase", + "MetricsProviderBase", +] diff --git a/aws_lambda_powertools/metrics/provider/base.py b/aws_lambda_powertools/metrics/provider/base.py new file mode 100644 index 00000000000..7617193033e --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/base.py @@ -0,0 +1,244 @@ +from __future__ import annotations + +import functools +import logging +from typing import Any, Callable, Dict, Optional + +from typing_extensions import Protocol + +logger = logging.getLogger(__name__) + +is_cold_start = True + + +class MetricsProviderBase(Protocol): + """ + Class for metric provider interface. + + This class serves as an interface for creating your own metric provider. Inherit from this class + and implement the required methods to define your specific metric provider. + + Usage: + 1. Inherit from this class. + 2. Implement the required methods specific to your metric provider. + 3. Customize the behavior and functionality of the metric provider in your subclass. + """ + + def add_metric(self, *args: Any, **kwargs: Any) -> Any: + """ + Abstract method for adding a metric. + + This method must be implemented in subclasses to add a metric and return a combined metrics dictionary. + + Parameters + ---------- + *args: + Positional arguments. + *kwargs: + Keyword arguments. + + Returns + ---------- + Dict + A combined metrics dictionary. + + Raises + ---------- + NotImplementedError + This method must be implemented in subclasses. + """ + raise NotImplementedError + + def serialize_metric_set(self, *args: Any, **kwargs: Any) -> Any: + """ + Abstract method for serialize a metric. + + This method must be implemented in subclasses to add a metric and return a combined metrics dictionary. + + Parameters + ---------- + *args: + Positional arguments. + *kwargs: + Keyword arguments. + + Returns + ---------- + Dict + Serialized metrics + + Raises + ---------- + NotImplementedError + This method must be implemented in subclasses. + """ + raise NotImplementedError + + # flush serialized data to output, or send to API directly + def flush_metrics(self, *args: Any, **kwargs) -> Any: + """ + Abstract method for flushing a metric. + + This method must be implemented in subclasses to add a metric and return a combined metrics dictionary. + + Parameters + ---------- + *args: + Positional arguments. + *kwargs: + Keyword arguments. + + Raises + ---------- + NotImplementedError + This method must be implemented in subclasses. + """ + raise NotImplementedError + + +class MetricsBase(Protocol): + """ + Class for metric template. + + This class serves as a template for creating your own metric class. Inherit from this class + and implement the necessary methods to define your specific metric. + + NOTE: need to improve this docstring + """ + + def add_metric(self, *args, **kwargs): + """ + Abstract method for adding a metric. + + This method must be implemented in subclasses to add a metric and return a combined metrics dictionary. + + Parameters + ---------- + *args: + Positional arguments. + *kwargs: + Keyword arguments. + + Returns + ---------- + Dict + A combined metrics dictionary. + + Raises + ---------- + NotImplementedError + This method must be implemented in subclasses. + """ + raise NotImplementedError + + def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: + """Manually flushes the metrics. This is normally not necessary, + unless you're running on other runtimes besides Lambda, where the @log_metrics + decorator already handles things for you. + + Parameters + ---------- + raise_on_empty_metrics : bool, optional + raise exception if no metrics are emitted, by default False + """ + raise NotImplementedError + + def add_cold_start_metric(self, metric_name: str, function_name: str) -> None: + """ + Add a cold start metric for a specific function. + + Parameters + ---------- + metric_name: str + The name of the cold start metric to add. + function_name: str + The name of the function associated with the cold start metric. + """ + raise NotImplementedError + + def log_metrics( + self, + lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, + capture_cold_start_metric: bool = False, + raise_on_empty_metrics: bool = False, + ): + """Decorator to serialize and publish metrics at the end of a function execution. + + Be aware that the log_metrics **does call* the decorated function (e.g. lambda_handler). + + Example + ------- + **Lambda function using tracer and metrics decorators** + + from aws_lambda_powertools import Metrics, Tracer + + metrics = Metrics(service="payment") + tracer = Tracer(service="payment") + + @tracer.capture_lambda_handler + @metrics.log_metrics + def handler(event, context): + ... + + Parameters + ---------- + lambda_handler : Callable[[Any, Any], Any], optional + lambda function handler, by default None + capture_cold_start_metric : bool, optional + captures cold start metric, by default False + raise_on_empty_metrics : bool, optional + raise exception if no metrics are emitted, by default False + default_dimensions: Dict[str, str], optional + metric dimensions as key=value that will always be present + + Raises + ------ + e + Propagate error received + """ + + # If handler is None we've been called with parameters + # Return a partial function with args filled + if lambda_handler is None: + logger.debug("Decorator called with parameters") + return functools.partial( + self.log_metrics, + capture_cold_start_metric=capture_cold_start_metric, + raise_on_empty_metrics=raise_on_empty_metrics, + ) + + @functools.wraps(lambda_handler) + def decorate(event, context): + try: + response = lambda_handler(event, context) + if capture_cold_start_metric: + self._add_cold_start_metric(context=context) + finally: + self.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) + + return response + + return decorate + + def _add_cold_start_metric(self, context: Any) -> None: + """Add cold start metric and function_name dimension + + Parameters + ---------- + context : Any + Lambda context + """ + global is_cold_start + if not is_cold_start: + return + + logger.debug("Adding cold start metric and function_name dimension") + self.add_cold_start_metric(metric_name="ColdStart", function_name=context.function_name) + + is_cold_start = False + + +def reset_cold_start_flag_provider(): + global is_cold_start + if not is_cold_start: + is_cold_start = True diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/__init__.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py new file mode 100644 index 00000000000..921fcee6045 --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py @@ -0,0 +1,496 @@ +from __future__ import annotations + +import datetime +import functools +import json +import logging +import numbers +import os +import warnings +from collections import defaultdict +from typing import Any, Callable, Dict, List, Optional, Union + +from aws_lambda_powertools.metrics.base import single_metric +from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError +from aws_lambda_powertools.metrics.provider import MetricsProviderBase +from aws_lambda_powertools.metrics.provider.cloudwatch_emf import cold_start +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import ( + MetricResolutionError, + MetricUnitError, +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit +from aws_lambda_powertools.metrics.types import MetricNameUnitResolution +from aws_lambda_powertools.shared import constants +from aws_lambda_powertools.shared.functions import resolve_env_var_choice + +logger = logging.getLogger(__name__) + + +class AmazonCloudWatchEMFProvider(MetricsProviderBase): + """Base class for metric functionality (namespace, metric, dimension, serialization) + + MetricManager creates metrics asynchronously thanks to CloudWatch Embedded Metric Format (EMF). + CloudWatch EMF can create up to 100 metrics per EMF object + and metrics, dimensions, and namespace created via MetricManager + will adhere to the schema, will be serialized and validated against EMF Schema. + + **Use `aws_lambda_powertools.metrics.metrics.Metrics` or + `aws_lambda_powertools.metrics.metric.single_metric` to create EMF metrics.** + + Environment variables + --------------------- + POWERTOOLS_METRICS_NAMESPACE : str + metric namespace to be set for all metrics + POWERTOOLS_SERVICE_NAME : str + service name used for default dimension + + Raises + ------ + MetricUnitError + When metric unit isn't supported by CloudWatch + MetricResolutionError + When metric resolution isn't supported by CloudWatch + MetricValueError + When metric value isn't a number + SchemaValidationError + When metric object fails EMF schema validation + """ + + def __init__( + self, + metric_set: Dict[str, Any] | None = None, + dimension_set: Dict | None = None, + namespace: str | None = None, + metadata_set: Dict[str, Any] | None = None, + service: str | None = None, + default_dimensions: Dict[str, Any] | None = None, + ): + self.metric_set = metric_set if metric_set is not None else {} + self.dimension_set = dimension_set if dimension_set is not None else {} + self.default_dimensions = default_dimensions or {} + self.namespace = resolve_env_var_choice(choice=namespace, env=os.getenv(constants.METRICS_NAMESPACE_ENV)) + self.service = resolve_env_var_choice(choice=service, env=os.getenv(constants.SERVICE_NAME_ENV)) + self.metadata_set = metadata_set if metadata_set is not None else {} + + self._metric_units = [unit.value for unit in MetricUnit] + self._metric_unit_valid_options = list(MetricUnit.__members__) + self._metric_resolutions = [resolution.value for resolution in MetricResolution] + + self.dimension_set.update(**self.default_dimensions) + + def add_metric( + self, + name: str, + unit: MetricUnit | str, + value: float, + resolution: MetricResolution | int = 60, + ) -> None: + """Adds given metric + + Example + ------- + **Add given metric using MetricUnit enum** + + metric.add_metric(name="BookingConfirmation", unit=MetricUnit.Count, value=1) + + **Add given metric using plain string as value unit** + + metric.add_metric(name="BookingConfirmation", unit="Count", value=1) + + **Add given metric with MetricResolution non default value** + + metric.add_metric(name="BookingConfirmation", unit="Count", value=1, resolution=MetricResolution.High) + + Parameters + ---------- + name : str + Metric name + unit : Union[MetricUnit, str] + `aws_lambda_powertools.helper.models.MetricUnit` + value : float + Metric value + resolution : Union[MetricResolution, int] + `aws_lambda_powertools.helper.models.MetricResolution` + + Raises + ------ + MetricUnitError + When metric unit is not supported by CloudWatch + MetricResolutionError + When metric resolution is not supported by CloudWatch + """ + if not isinstance(value, numbers.Number): + raise MetricValueError(f"{value} is not a valid number") + + unit = self._extract_metric_unit_value(unit=unit) + resolution = self._extract_metric_resolution_value(resolution=resolution) + metric: Dict = self.metric_set.get(name, defaultdict(list)) + metric["Unit"] = unit + metric["StorageResolution"] = resolution + metric["Value"].append(float(value)) + logger.debug(f"Adding metric: {name} with {metric}") + self.metric_set[name] = metric + + if len(self.metric_set) == MAX_METRICS or len(metric["Value"]) == MAX_METRICS: + logger.debug(f"Exceeded maximum of {MAX_METRICS} metrics - Publishing existing metric set") + metrics = self.serialize_metric_set() + print(json.dumps(metrics)) + + # clear metric set only as opposed to metrics and dimensions set + # since we could have more than 100 metrics + self.metric_set.clear() + + def serialize_metric_set( + self, + metrics: Dict | None = None, + dimensions: Dict | None = None, + metadata: Dict | None = None, + ) -> Dict: + """Serializes metric and dimensions set + + Parameters + ---------- + metrics : Dict, optional + Dictionary of metrics to serialize, by default None + dimensions : Dict, optional + Dictionary of dimensions to serialize, by default None + metadata: Dict, optional + Dictionary of metadata to serialize, by default None + + Example + ------- + **Serialize metrics into EMF format** + + metrics = MetricManager() + # ...add metrics, dimensions, namespace + ret = metrics.serialize_metric_set() + + Returns + ------- + Dict + Serialized metrics following EMF specification + + Raises + ------ + SchemaValidationError + Raised when serialization fail schema validation + """ + if metrics is None: # pragma: no cover + metrics = self.metric_set + + if dimensions is None: # pragma: no cover + dimensions = self.dimension_set + + if metadata is None: # pragma: no cover + metadata = self.metadata_set + + if self.service and not self.dimension_set.get("service"): + # self.service won't be a float + self.add_dimension(name="service", value=self.service) + + if len(metrics) == 0: + raise SchemaValidationError("Must contain at least one metric.") + + if self.namespace is None: + raise SchemaValidationError("Must contain a metric namespace.") + + logger.debug({"details": "Serializing metrics", "metrics": metrics, "dimensions": dimensions}) + + # For standard resolution metrics, don't add StorageResolution field to avoid unnecessary ingestion of data into cloudwatch # noqa E501 + # Example: [ { "Name": "metric_name", "Unit": "Count"} ] # noqa ERA001 + # + # In case using high-resolution metrics, add StorageResolution field + # Example: [ { "Name": "metric_name", "Unit": "Count", "StorageResolution": 1 } ] # noqa ERA001 + metric_definition: List[MetricNameUnitResolution] = [] + metric_names_and_values: Dict[str, float] = {} # { "metric_name": 1.0 } + + for metric_name in metrics: + metric: dict = metrics[metric_name] + metric_value: int = metric.get("Value", 0) + metric_unit: str = metric.get("Unit", "") + metric_resolution: int = metric.get("StorageResolution", 60) + + metric_definition_data: MetricNameUnitResolution = {"Name": metric_name, "Unit": metric_unit} + + # high-resolution metrics + if metric_resolution == 1: + metric_definition_data["StorageResolution"] = metric_resolution + + metric_definition.append(metric_definition_data) + + metric_names_and_values.update({metric_name: metric_value}) + + return { + "_aws": { + "Timestamp": int(datetime.datetime.now().timestamp() * 1000), # epoch + "CloudWatchMetrics": [ + { + "Namespace": self.namespace, # "test_namespace" + "Dimensions": [list(dimensions.keys())], # [ "service" ] + "Metrics": metric_definition, + }, + ], + }, + **dimensions, # "service": "test_service" + **metadata, # "username": "test" + **metric_names_and_values, # "single_metric": 1.0 + } + + def add_dimension(self, name: str, value: str) -> None: + """Adds given dimension to all metrics + + Example + ------- + **Add a metric dimensions** + + metric.add_dimension(name="operation", value="confirm_booking") + + Parameters + ---------- + name : str + Dimension name + value : str + Dimension value + """ + logger.debug(f"Adding dimension: {name}:{value}") + if len(self.dimension_set) == MAX_DIMENSIONS: + raise SchemaValidationError( + f"Maximum number of dimensions exceeded ({MAX_DIMENSIONS}): Unable to add dimension {name}.", + ) + # Cast value to str according to EMF spec + # Majority of values are expected to be string already, so + # checking before casting improves performance in most cases + self.dimension_set[name] = value if isinstance(value, str) else str(value) + + def add_metadata(self, key: str, value: Any) -> None: + """Adds high cardinal metadata for metrics object + + This will not be available during metrics visualization. + Instead, this will be searchable through logs. + + If you're looking to add metadata to filter metrics, then + use add_dimensions method. + + Example + ------- + **Add metrics metadata** + + metric.add_metadata(key="booking_id", value="booking_id") + + Parameters + ---------- + key : str + Metadata key + value : any + Metadata value + """ + logger.debug(f"Adding metadata: {key}:{value}") + + # Cast key to str according to EMF spec + # Majority of keys are expected to be string already, so + # checking before casting improves performance in most cases + if isinstance(key, str): + self.metadata_set[key] = value + else: + self.metadata_set[str(key)] = value + + def clear_metrics(self) -> None: + logger.debug("Clearing out existing metric set from memory") + self.metric_set.clear() + self.dimension_set.clear() + self.metadata_set.clear() + self.set_default_dimensions(**self.default_dimensions) + + def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: + """Manually flushes the metrics. This is normally not necessary, + unless you're running on other runtimes besides Lambda, where the @log_metrics + decorator already handles things for you. + + Parameters + ---------- + raise_on_empty_metrics : bool, optional + raise exception if no metrics are emitted, by default False + """ + if not raise_on_empty_metrics and not self.metric_set: + warnings.warn( + "No application metrics to publish. The cold-start metric may be published if enabled. " + "If application metrics should never be empty, consider using 'raise_on_empty_metrics'", + stacklevel=2, + ) + else: + logger.debug("Flushing existing metrics") + metrics = self.serialize_metric_set() + print(json.dumps(metrics, separators=(",", ":"))) + self.clear_metrics() + + def log_metrics( + self, + lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, + capture_cold_start_metric: bool = False, + raise_on_empty_metrics: bool = False, + default_dimensions: Dict[str, str] | None = None, + ): + """Decorator to serialize and publish metrics at the end of a function execution. + + Be aware that the log_metrics **does call* the decorated function (e.g. lambda_handler). + + Example + ------- + **Lambda function using tracer and metrics decorators** + + from aws_lambda_powertools import Metrics, Tracer + + metrics = Metrics(service="payment") + tracer = Tracer(service="payment") + + @tracer.capture_lambda_handler + @metrics.log_metrics + def handler(event, context): + ... + + Parameters + ---------- + lambda_handler : Callable[[Any, Any], Any], optional + lambda function handler, by default None + capture_cold_start_metric : bool, optional + captures cold start metric, by default False + raise_on_empty_metrics : bool, optional + raise exception if no metrics are emitted, by default False + default_dimensions: Dict[str, str], optional + metric dimensions as key=value that will always be present + + Raises + ------ + e + Propagate error received + """ + + # If handler is None we've been called with parameters + # Return a partial function with args filled + if lambda_handler is None: + logger.debug("Decorator called with parameters") + return functools.partial( + self.log_metrics, + capture_cold_start_metric=capture_cold_start_metric, + raise_on_empty_metrics=raise_on_empty_metrics, + default_dimensions=default_dimensions, + ) + + @functools.wraps(lambda_handler) + def decorate(event, context): + try: + if default_dimensions: + self.set_default_dimensions(**default_dimensions) + response = lambda_handler(event, context) + if capture_cold_start_metric: + self._add_cold_start_metric(context=context) + finally: + self.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) + + return response + + return decorate + + def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int: + """Return metric value from metric unit whether that's str or MetricResolution enum + + Parameters + ---------- + unit : Union[int, MetricResolution] + Metric resolution + + Returns + ------- + int + Metric resolution value must be 1 or 60 + + Raises + ------ + MetricResolutionError + When metric resolution is not supported by CloudWatch + """ + if isinstance(resolution, MetricResolution): + return resolution.value + + if isinstance(resolution, int) and resolution in self._metric_resolutions: + return resolution + + raise MetricResolutionError( + f"Invalid metric resolution '{resolution}', expected either option: {self._metric_resolutions}", # noqa: E501 + ) + + def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: + """Return metric value from metric unit whether that's str or MetricUnit enum + + Parameters + ---------- + unit : Union[str, MetricUnit] + Metric unit + + Returns + ------- + str + Metric unit value (e.g. "Seconds", "Count/Second") + + Raises + ------ + MetricUnitError + When metric unit is not supported by CloudWatch + """ + + if isinstance(unit, str): + if unit in self._metric_unit_valid_options: + unit = MetricUnit[unit].value + + if unit not in self._metric_units: + raise MetricUnitError( + f"Invalid metric unit '{unit}', expected either option: {self._metric_unit_valid_options}", + ) + + if isinstance(unit, MetricUnit): + unit = unit.value + + return unit + + def _add_cold_start_metric(self, context: Any) -> None: + """Add cold start metric and function_name dimension + + Parameters + ---------- + context : Any + Lambda context + """ + if cold_start.is_cold_start: + logger.debug("Adding cold start metric and function_name dimension") + with single_metric(name="ColdStart", unit=MetricUnit.Count, value=1, namespace=self.namespace) as metric: + metric.add_dimension(name="function_name", value=context.function_name) + if self.service: + metric.add_dimension(name="service", value=str(self.service)) + cold_start.is_cold_start = False + + def set_default_dimensions(self, **dimensions) -> None: + """Persist dimensions across Lambda invocations + + Parameters + ---------- + dimensions : Dict[str, Any], optional + metric dimensions as key=value + + Example + ------- + **Sets some default dimensions that will always be present across metrics and invocations** + + from aws_lambda_powertools import Metrics + + metrics = Metrics(namespace="ServerlessAirline", service="payment") + metrics.set_default_dimensions(environment="demo", another="one") + + @metrics.log_metrics() + def lambda_handler(): + return True + """ + for name, value in dimensions.items(): + self.add_dimension(name, value) + + self.default_dimensions.update(**dimensions) diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cold_start.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cold_start.py new file mode 100644 index 00000000000..c6ef67bd787 --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cold_start.py @@ -0,0 +1,9 @@ +from __future__ import annotations + +is_cold_start = True + + +def reset_cold_start_flag(): + global is_cold_start + if not is_cold_start: + is_cold_start = True diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py new file mode 100644 index 00000000000..d8f5da0cec8 --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/constants.py @@ -0,0 +1,2 @@ +MAX_DIMENSIONS = 29 +MAX_METRICS = 100 diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py new file mode 100644 index 00000000000..6ac2d932ea7 --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py @@ -0,0 +1,10 @@ +class MetricUnitError(Exception): + """When metric unit is not supported by CloudWatch""" + + pass + + +class MetricResolutionError(Exception): + """When metric resolution is not supported by CloudWatch""" + + pass diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py new file mode 100644 index 00000000000..ea11bb997bb --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/metric_properties.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from enum import Enum + + +class MetricUnit(Enum): + 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" + BytesPerSecond = "Bytes/Second" + KilobytesPerSecond = "Kilobytes/Second" + MegabytesPerSecond = "Megabytes/Second" + GigabytesPerSecond = "Gigabytes/Second" + TerabytesPerSecond = "Terabytes/Second" + BitsPerSecond = "Bits/Second" + KilobitsPerSecond = "Kilobits/Second" + MegabitsPerSecond = "Megabits/Second" + GigabitsPerSecond = "Gigabits/Second" + TerabitsPerSecond = "Terabits/Second" + CountPerSecond = "Count/Second" + + +class MetricResolution(Enum): + Standard = 60 + High = 1 diff --git a/docs/maintainers.md b/docs/maintainers.md index 455d33f6d8a..8f3a1980141 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -288,6 +288,7 @@ Ensure the repo highlights features that should be elevated to the project roadm Add integration checks that validate pull requests and pushes to ease the burden on Pull Request reviewers. Continuously revisit areas of improvement to reduce operational burden in all parties involved. ### Negative Impact on the Project + Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank"} violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. diff --git a/poetry.lock b/poetry.lock index 3fcd22c4a4f..1f0da79064c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -93,17 +93,17 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-alpha" -version = "2.88.0a0" +version = "2.89.0a0" description = "The CDK Construct Library for AWS::APIGatewayv2" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-alpha-2.88.0a0.tar.gz", hash = "sha256:87f746336687ba519263ced055912eff8bef643629d5f1eb17f3cdef2408d441"}, - {file = "aws_cdk.aws_apigatewayv2_alpha-2.88.0a0-py3-none-any.whl", hash = "sha256:be0da36994bedbbc4b82db245fa5f3fae59f95665c9d60527f7ece5e9b4df6a4"}, + {file = "aws-cdk.aws-apigatewayv2-alpha-2.89.0a0.tar.gz", hash = "sha256:8300431d4ef9d869066ad5dba955a6b9eca4825eb4ffcdb03d9ce34f82509d6a"}, + {file = "aws_cdk.aws_apigatewayv2_alpha-2.89.0a0-py3-none-any.whl", hash = "sha256:64a84542822bd085b03ac40e39f15c3fee1aaf649a0df34ecf0f288f7bc84c78"}, ] [package.dependencies] -aws-cdk-lib = "2.88.0" +aws-cdk-lib = "2.89.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -111,18 +111,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-authorizers-alpha" -version = "2.88.0a0" +version = "2.89.0a0" description = "Authorizers for AWS APIGateway V2" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.88.0a0.tar.gz", hash = "sha256:60f3a0ac560b6f3ff729b50110841f134eecd842bf69d02602e750589a35cbff"}, - {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.88.0a0-py3-none-any.whl", hash = "sha256:85e57c5a7a86829a594634f82448c95443d4d29c30baf361257e57fd4df24efc"}, + {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.89.0a0.tar.gz", hash = "sha256:efa23f021efdca83f037569d41d7e96023c3750417fc976023688397f7f57715"}, + {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.89.0a0-py3-none-any.whl", hash = "sha256:7b56ea2889e8a340bfd4feb67f0798827bf58090d368763a59cd0223fe2dd916"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.88.0.a0" -aws-cdk-lib = "2.88.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.89.0.a0" +aws-cdk-lib = "2.89.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -130,18 +130,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-integrations-alpha" -version = "2.88.0a0" +version = "2.89.0a0" description = "Integrations for AWS APIGateway V2" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.88.0a0.tar.gz", hash = "sha256:a604acb1dde9840ccc24c23aba542b42764c826c8100b787e16198113d6b6e89"}, - {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.88.0a0-py3-none-any.whl", hash = "sha256:ff06fc8192bece85f82f7b008c93e5ada8af1466612b0b76287edce8c5415c47"}, + {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.89.0a0.tar.gz", hash = "sha256:81469d688a611d9ab10d528923692eba685cbb04a5d3401c02a4530b001a6a77"}, + {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.89.0a0-py3-none-any.whl", hash = "sha256:3367cf5fa8e4bb1939fcd60e919af00ecc6d97a1d046938af25b9c5bef26b4c1"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.88.0.a0" -aws-cdk-lib = "2.88.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.89.0.a0" +aws-cdk-lib = "2.89.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -149,19 +149,19 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.88.0" +version = "2.89.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk-lib-2.88.0.tar.gz", hash = "sha256:6514217e6485133b30848f11b6c78ec955d41bed4e39e5ba4bea49c379830e56"}, - {file = "aws_cdk_lib-2.88.0-py3-none-any.whl", hash = "sha256:db4716689cb94e249b8c672139221f1d7866b7d6caca314b52552fa3bacab22c"}, + {file = "aws-cdk-lib-2.89.0.tar.gz", hash = "sha256:8fbd1d4ee0ffeb67bcc845bef5a10575dbc678ad07f74cdb3cb4243afc433db7"}, + {file = "aws_cdk_lib-2.89.0-py3-none-any.whl", hash = "sha256:92eeebd77fe17b36029fae20f46eb601710485ea7c808c3d33fe1c71fee125bd"}, ] [package.dependencies] "aws-cdk.asset-awscli-v1" = ">=2.2.200,<3.0.0" "aws-cdk.asset-kubectl-v20" = ">=2.1.2,<3.0.0" -"aws-cdk.asset-node-proxy-agent-v5" = ">=2.0.165,<3.0.0" +"aws-cdk.asset-node-proxy-agent-v5" = ">=2.0.166,<3.0.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -183,13 +183,13 @@ requests = ">=0.14.0" [[package]] name = "aws-sam-translator" -version = "1.71.0" +version = "1.72.0" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "aws-sam-translator-1.71.0.tar.gz", hash = "sha256:a3ea80aeb116d7978b26ac916d2a5a24d012b742bf28262b17769c4b886e8fba"}, - {file = "aws_sam_translator-1.71.0-py3-none-any.whl", hash = "sha256:17fb87c8137d8d49e7a978396b2b3b279211819dee44618415aab1e99c2cb659"}, + {file = "aws-sam-translator-1.72.0.tar.gz", hash = "sha256:e688aac30943bfe0352147b792d8bbe7c1b5ed648747cd7ef6280875b249e2d8"}, + {file = "aws_sam_translator-1.72.0-py3-none-any.whl", hash = "sha256:69fe3914d61ae6690034c3fc1055743e5415d83c59c35ec5ec9ceb26cc65c8a1"}, ] [package.dependencies] @@ -291,17 +291,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.28.9" +version = "1.28.16" description = "The AWS SDK for Python" optional = false python-versions = ">= 3.7" files = [ - {file = "boto3-1.28.9-py3-none-any.whl", hash = "sha256:01f078047eb4d238c6b9c6cc623f2af33b4ae67980c5326691e35cb5493ff6c7"}, - {file = "boto3-1.28.9.tar.gz", hash = "sha256:4cc0c6005be910e52077227e670930ab55a41ba86cdb6d1c052571d08cd4d32c"}, + {file = "boto3-1.28.16-py3-none-any.whl", hash = "sha256:d8e31f69fb919025a5961f8fbeb51fe92e2f753beb37fc1853138667a231cdaa"}, + {file = "boto3-1.28.16.tar.gz", hash = "sha256:aea48aedf3e8676e598e3202e732295064a4fcad5f2d2d2a699368b8c3ab492c"}, ] [package.dependencies] -botocore = ">=1.31.9,<1.32.0" +botocore = ">=1.31.16,<1.32.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.6.0,<0.7.0" @@ -310,13 +310,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.31.9" +version = "1.31.16" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.7" files = [ - {file = "botocore-1.31.9-py3-none-any.whl", hash = "sha256:e56ccd3536a90094ea5b176b5dd33bfe4f049efdf71af468ea1661bd424c787d"}, - {file = "botocore-1.31.9.tar.gz", hash = "sha256:bd849d3ac95f1781385ed831d753a04a3ec870a59d6598175aaedd71dc2baf5f"}, + {file = "botocore-1.31.16-py3-none-any.whl", hash = "sha256:92b240e2cb7b3afae5361651d2f48ee582f45d2dab53aef76eef7eec1d3ce582"}, + {file = "botocore-1.31.16.tar.gz", hash = "sha256:563e15979e763b93d78de58d0fc065f8615be12f41bab42f5ad9f412b6a224b3"}, ] [package.dependencies] @@ -1143,19 +1143,20 @@ restructuredtext = ["rst2ansi"] [[package]] name = "markdown" -version = "3.3.7" -description = "Python implementation of Markdown." +version = "3.4.4" +description = "Python implementation of John Gruber's Markdown." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"}, - {file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"}, + {file = "Markdown-3.4.4-py3-none-any.whl", hash = "sha256:a4c1b65c0957b4bd9e7d86ddc7b3c9868fb9670660f6f99f6d1bca8954d5a941"}, + {file = "Markdown-3.4.4.tar.gz", hash = "sha256:225c6123522495d4119a90b3a3ba31a1e87a70369e03f14799ea9c0d7183a3d6"}, ] [package.dependencies] importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} [package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.0)", "mkdocs-nature (>=0.4)"] testing = ["coverage", "pyyaml"] [[package]] @@ -1625,13 +1626,13 @@ files = [ [[package]] name = "pathspec" -version = "0.11.1" +version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.7" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] [[package]] @@ -1673,21 +1674,21 @@ files = [ [[package]] name = "platformdirs" -version = "3.9.1" +version = "3.10.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"}, - {file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"}, + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] [package.dependencies] -typing-extensions = {version = ">=4.6.3", markers = "python_version < \"3.8\""} +typing-extensions = {version = ">=4.7.1", markers = "python_version < \"3.8\""} [package.extras] -docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" @@ -2199,13 +2200,13 @@ decorator = ">=3.4.2" [[package]] name = "rich" -version = "13.4.2" +version = "13.5.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.4.2-py3-none-any.whl", hash = "sha256:8f87bc7ee54675732fa66a05ebfe489e27264caeeff3728c945d25971b6485ec"}, - {file = "rich-13.4.2.tar.gz", hash = "sha256:d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898"}, + {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, + {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, ] [package.dependencies] @@ -2276,13 +2277,13 @@ pbr = "*" [[package]] name = "sentry-sdk" -version = "1.29.0" +version = "1.29.2" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.29.0.tar.gz", hash = "sha256:5053aa7647533b207417cea5f3ee2d5e13aea7001dbb711f46348d7a72597d60"}, - {file = "sentry_sdk-1.29.0-py2.py3-none-any.whl", hash = "sha256:78c764cbec1967c41e24967e9a4a5d1e67a7bc960d125d905f94c068a0300ac9"}, + {file = "sentry-sdk-1.29.2.tar.gz", hash = "sha256:a99ee105384788c3f228726a88baf515fe7b5f1d2d0f215a03d194369f158df7"}, + {file = "sentry_sdk-1.29.2-py2.py3-none-any.whl", hash = "sha256:3e17215d8006612e2df02b0e73115eb8376c37e3f586d8436fa41644e605074d"}, ] [package.dependencies] diff --git a/ruff.toml b/ruff.toml index 424040ede1f..be67606bbe5 100644 --- a/ruff.toml +++ b/ruff.toml @@ -69,3 +69,5 @@ split-on-trailing-comma = true "tests/e2e/utils/data_fetcher/__init__.py" = ["F401"] "aws_lambda_powertools/utilities/data_classes/s3_event.py" = ["A003"] "aws_lambda_powertools/utilities/parser/models/__init__.py" = ["E402"] +# Maintenance: we're keeping EphemeralMetrics code in case of Hyrum's law so we can quickly revert it +"aws_lambda_powertools/metrics/metrics.py" = ["ERA001"] diff --git a/tests/functional/test_metrics.py b/tests/functional/test_metrics.py index 5a6222f248d..1eed6c82294 100644 --- a/tests/functional/test_metrics.py +++ b/tests/functional/test_metrics.py @@ -5,21 +5,25 @@ import pytest -from aws_lambda_powertools import Metrics, single_metric from aws_lambda_powertools.metrics import ( EphemeralMetrics, MetricResolution, MetricResolutionError, + Metrics, MetricUnit, MetricUnitError, MetricValueError, SchemaValidationError, + single_metric, ) -from aws_lambda_powertools.metrics.base import ( - MAX_DIMENSIONS, - MetricManager, - reset_cold_start_flag, +from aws_lambda_powertools.metrics.provider import ( + MetricsBase, + MetricsProviderBase, ) +from aws_lambda_powertools.metrics.provider.base import reset_cold_start_flag_provider +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import AmazonCloudWatchEMFProvider +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cold_start import reset_cold_start_flag +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS @pytest.fixture(scope="function", autouse=True) @@ -110,7 +114,7 @@ def serialize_metrics( metadatas: List[Dict] = None, ) -> Dict: """Helper function to build EMF object from a list of metrics, dimensions""" - my_metrics = MetricManager(namespace=namespace) + my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace) for dimension in dimensions: my_metrics.add_dimension(**dimension) @@ -127,7 +131,7 @@ def serialize_metrics( def serialize_single_metric(metric: Dict, dimension: Dict, namespace: str, metadata: Dict = None) -> Dict: """Helper function to build EMF object from a given metric, dimension and namespace""" - my_metrics = MetricManager(namespace=namespace) + my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace) my_metrics.add_metric(**metric) my_metrics.add_dimension(**dimension) @@ -228,6 +232,27 @@ def test_single_metric_default_dimensions_inherit(capsys, metric, dimension, nam assert expected == output +def test_log_metrics_preconfigured_provider(capsys, metrics, dimensions, namespace): + # GIVEN Metrics is initialized + provider = AmazonCloudWatchEMFProvider(namespace=namespace) + my_metrics = Metrics(provider=provider) + for metric in metrics: + my_metrics.add_metric(**metric) + for dimension in dimensions: + my_metrics.add_dimension(**dimension) + + # WHEN we manually the metrics + my_metrics.flush_metrics() + + output = capture_metrics_output(capsys) + expected = serialize_metrics(metrics=metrics, dimensions=dimensions, namespace=namespace) + + # THEN we should have no exceptions + # and a valid EMF object should be flushed correctly + remove_timestamp(metrics=[output, expected]) + assert expected == output + + def test_log_metrics(capsys, metrics, dimensions, namespace): # GIVEN Metrics is initialized my_metrics = Metrics(namespace=namespace) @@ -1010,7 +1035,7 @@ def test_metric_manage_metadata_set(): expected_dict = {"setting": "On"} try: - metric = MetricManager(metadata_set=expected_dict) + metric = AmazonCloudWatchEMFProvider(metadata_set=expected_dict) assert metric.metadata_set == expected_dict except AttributeError: pytest.fail("AttributeError should not be raised") @@ -1052,6 +1077,20 @@ def test_clear_default_dimensions(namespace): assert not my_metrics.default_dimensions +def test_clear_default_dimensions_with_provider(namespace): + # GIVEN Metrics is initialized with provider and we persist a set of default dimensions + my_provider = AmazonCloudWatchEMFProvider(namespace=namespace) + my_metrics = Metrics(provider=my_provider) + my_metrics.set_default_dimensions(environment="test", log_group="/lambda/test") + + # WHEN they are removed via clear_default_dimensions method + my_metrics.clear_default_dimensions() + + # THEN there should be no default dimensions in provider and metrics + assert not my_metrics.default_dimensions + assert not my_provider.default_dimensions + + def test_default_dimensions_across_instances(namespace): # GIVEN Metrics is initialized and we persist a set of default dimensions my_metrics = Metrics(namespace=namespace) @@ -1143,6 +1182,7 @@ def test_ephemeral_metrics_isolated_data_set_with_default_dimension(metric, dime # GIVEN two EphemeralMetrics instances are initialized # One with default dimension and another without my_metrics = EphemeralMetrics(namespace=namespace) + my_metrics.set_default_dimensions(dev="powertools") isolated_metrics = EphemeralMetrics(namespace=namespace) @@ -1211,3 +1251,159 @@ def lambda_handler(evt, ctx): output = capture_metrics_output_multiple_emf_objects(capsys) assert len(output) == 2 + + +@pytest.fixture +def metrics_provider() -> MetricsProviderBase: + class MetricsProvider: + def __init__(self): + self.metric_store: List = [] + self.result: str + super().__init__() + + def add_metric(self, name: str, value: float, tag: List = None, *args, **kwargs): + self.metric_store.append({"name": name, "value": value, "tag": tag}) + + def serialize(self, raise_on_empty_metrics: bool = False, *args, **kwargs): + if raise_on_empty_metrics and len(self.metric_store) == 0: + raise SchemaValidationError("Must contain at least one metric.") + + self.result = json.dumps(self.metric_store) + + def flush(self, *args, **kwargs): + print(self.result) + + def clear(self): + self.result = "" + self.metric_store = [] + + return MetricsProvider + + +@pytest.fixture +def metrics_class() -> MetricsBase: + class MetricsClass(MetricsBase): + def __init__(self, provider): + self.provider = provider + super().__init__() + + def add_metric(self, name: str, value: float, tag: List = None, *args, **kwargs): + self.provider.add_metric(name=name, value=value, tag=tag) + + def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: + self.provider.serialize(raise_on_empty_metrics=raise_on_empty_metrics) + self.provider.flush() + self.provider.clear() + + def add_cold_start_metric(self, metric_name: str, function_name: str) -> None: + self.provider.add_metric(name=metric_name, value=1, function_name=function_name) + + return MetricsClass + + +def test_metrics_provider_basic(capsys, metrics_provider, metric): + provider = metrics_provider() + provider.add_metric(**metric) + provider.serialize() + provider.flush() + output = capture_metrics_output(capsys) + assert output[0]["name"] == metric["name"] + assert output[0]["value"] == metric["value"] + + +def test_metrics_provider_class_basic(capsys, metrics_provider, metrics_class, metric): + metrics = metrics_class(provider=metrics_provider()) + metrics.add_metric(**metric) + metrics.flush_metrics() + output = capture_metrics_output(capsys) + assert output[0]["name"] == metric["name"] + assert output[0]["value"] == metric["value"] + + +def test_metrics_provider_class_decorate(metrics_class, metrics_provider): + # GIVEN Metrics is initialized + my_metrics = metrics_class(provider=metrics_provider()) + + # WHEN log_metrics is used to serialize metrics + @my_metrics.log_metrics + def lambda_handler(evt, context): + return True + + # THEN log_metrics should invoke the function it decorates + # and return no error if we have a namespace and dimension + assert lambda_handler({}, {}) is True + + +def test_metrics_provider_class_coldstart(capsys, metrics_provider, metrics_class): + my_metrics = metrics_class(provider=metrics_provider()) + + # WHEN log_metrics is used with capture_cold_start_metric + @my_metrics.log_metrics(capture_cold_start_metric=True) + def lambda_handler(evt, context): + pass + + LambdaContext = namedtuple("LambdaContext", "function_name") + lambda_handler({}, LambdaContext("example_fn")) + + output = capture_metrics_output(capsys) + + # THEN ColdStart metric and function_name and service dimension should be logged + assert output[0]["name"] == "ColdStart" + + +def test_metrics_provider_class_no_coldstart(capsys, metrics_provider, metrics_class): + reset_cold_start_flag_provider() + my_metrics = metrics_class(provider=metrics_provider()) + + # WHEN log_metrics is used with capture_cold_start_metric + @my_metrics.log_metrics(capture_cold_start_metric=True) + def lambda_handler(evt, context): + pass + + LambdaContext = namedtuple("LambdaContext", "function_name") + lambda_handler({}, LambdaContext("example_fn")) + _ = capture_metrics_output(capsys) + # drop first one + + lambda_handler({}, LambdaContext("example_fn")) + output = capture_metrics_output(capsys) + + # no coldstart is here + assert "ColdStart" not in json.dumps(output) + + +def test_metric_provider_raise_on_empty_metrics(metrics_provider, metrics_class): + # GIVEN Metrics is initialized + my_metrics = metrics_class(provider=metrics_provider()) + + # WHEN log_metrics is used with raise_on_empty_metrics param and has no metrics + @my_metrics.log_metrics(raise_on_empty_metrics=True) + def lambda_handler(evt, context): + pass + + # THEN the raised exception should be SchemaValidationError + # and specifically about the lack of Metrics + with pytest.raises(SchemaValidationError, match="Must contain at least one metric."): + lambda_handler({}, {}) + + +def test_log_metrics_capture_cold_start_metric_once_with_provider_and_ephemeral(capsys, namespace, service): + # GIVEN Metrics is initialized + my_metrics = Metrics(service=service, namespace=namespace) + my_isolated_metrics = EphemeralMetrics(service=service, namespace=namespace) + + # WHEN log_metrics is used with capture_cold_start_metric + @my_metrics.log_metrics(capture_cold_start_metric=True) + @my_isolated_metrics.log_metrics(capture_cold_start_metric=True) + def lambda_handler(evt, context): + pass + + LambdaContext = namedtuple("LambdaContext", "function_name") + lambda_handler({}, LambdaContext("example_fn")) + + output = capture_metrics_output(capsys) + + # THEN ColdStart metric and function_name and service dimension should be logged + assert output["ColdStart"] == [1.0] + assert output["function_name"] == "example_fn" + assert output["service"] == service From 5ae9d5e51d53aa104e14f8cbaa5b99475af84ad3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 09:05:44 +0200 Subject: [PATCH 43/92] chore(ci): changelog rebuild (#2908) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b4870691a..08b6605bcbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,28 +16,41 @@ * **navigation:** add nofollow attribute ([#2842](https://github.com/aws-powertools/powertools-lambda-python/issues/2842)) * **tutorial:** add support for Python 3.11 ([#2860](https://github.com/aws-powertools/powertools-lambda-python/issues/2860)) +## Features + +* **metrics:** support to bring your own metrics provider ([#2194](https://github.com/aws-powertools/powertools-lambda-python/issues/2194)) + ## Maintenance +* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) * **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) +* **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) +* **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) -* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) -* **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) +* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) +* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) -* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) -* **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) +* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) From 88ece0441090aa94026896509505ea01c601bc6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 08:33:00 -0300 Subject: [PATCH 44/92] chore(deps-dev): bump ruff from 0.0.281 to 0.0.282 (#2905) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.281 to 0.0.282. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.0.281...v0.0.282) --- updated-dependencies: - dependency-name: ruff 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> --- poetry.lock | 38 +++++++++++++++++++------------------- pyproject.toml | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1f0da79064c..d8e044fa292 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2219,28 +2219,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.281" +version = "0.0.282" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.281-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:418fbddfd3dba4d7b11e4e016eacc40d321ff0b7d3637c7ba9ad3ee0474c9a35"}, - {file = "ruff-0.0.281-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c086bf3968d5cb2b4f31a586fc73bc42cb688c32f4c992ff161d4ce19f551cf2"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0162b149a94f6007768820bcdf4ccb7e90a21655aac829ace49f4682d0565fdb"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3495175e6d85a01d3da409a079461a5a3c15b70237cc82550ad8c1f091002c8"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae0b836c03a7010527bb56384a4e3718e0958e32bea64459879aacdcb65c4945"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6d34cae6ef6c6b6fd6d4f09271fbf635db49e6b788da1b2e1dea11a29f1c2a11"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd3c94260a148e955fb46f41d4bcecd857c75794e9f06ebfa7f9be65cfed9621"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ccb875a4000bcba6cc61cb9d3cd5969d6b0921b5234f0ef99ad75f74e8935ef"}, - {file = "ruff-0.0.281-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f5b8ccaabad61e2d50494df820b7bafd94eac13f10d2d8b831994c1618801a9"}, - {file = "ruff-0.0.281-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:cbf279fd9c2ca674896656df2d82831010afd336a6703a060fe08d6f2358e47b"}, - {file = "ruff-0.0.281-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:24d0defeb2c6a1b16a4230840d1138e08bc4ef2318496fa6ff7ddbf3a443626f"}, - {file = "ruff-0.0.281-py3-none-musllinux_1_2_i686.whl", hash = "sha256:54bab7128167057ee5987bbd9f925fbf105071068de9d8474ca7c38f684b8463"}, - {file = "ruff-0.0.281-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:29a22b7a6433ce0b4e601897e8a5dd58a75c75c01afee9b8922ebbdd1fe51e51"}, - {file = "ruff-0.0.281-py3-none-win32.whl", hash = "sha256:7b781f6a7ed35196e6565ed32f57d07b852b0dcd7158c6c7669c8b5d0f8cf97a"}, - {file = "ruff-0.0.281-py3-none-win_amd64.whl", hash = "sha256:70f921438bf09f04c0547cf64c137c87ef33cbec2b64be12b8caa87df261a016"}, - {file = "ruff-0.0.281-py3-none-win_arm64.whl", hash = "sha256:42a92a62fc841f7444821444553fd6e1e700bb55348f24e8ec39afdd4e3d0312"}, - {file = "ruff-0.0.281.tar.gz", hash = "sha256:bab2cdfa78754315cccc2b4d46ad6181aabb29e89747a3b135a4b85e11baa025"}, + {file = "ruff-0.0.282-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:01b76309ddab16eb258dabc5e86e73e6542f59f3ea6b4ab886ecbcfc80ce062c"}, + {file = "ruff-0.0.282-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e177cbb6dc0b1dbef5e999900d798b73e33602abf9b6c62d5d2cbe101026d931"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5374b40b6d860d334d28678a53a92f0bf04b53acdf0395900361ad54ce71cd1d"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d1ccbceb44e94fe2205b63996166e98a513a19ed23ec01d7193b7494b94ba30d"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eee9c8c50bc77eb9c0811c91d9d67ff39fe4f394c2f44ada37dac6d45e50c9f1"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:826e4de98e91450a6fe699a4e4a7cf33b9a90a2c5c270dc5b202241c37359ff8"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d99758f8bbcb8f8da99acabf711ffad5e7a015247adf27211100b3586777fd56"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f30c9958ab9cb02bf0c574c629e87c19454cbbdb82750e49e3d1559a5a8f216"}, + {file = "ruff-0.0.282-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47a7a9366ab8e4ee20df9339bef172eec7b2e9e123643bf3ede005058f5b114e"}, + {file = "ruff-0.0.282-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1f05f5e6d6df6f8b1974c08f963c33f0a4d8cfa15cba12d35ca3ece8e9be5b1f"}, + {file = "ruff-0.0.282-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0710ea2cadc504b96c1d94c414a7802369d0fff2ab7c94460344bba69135cb40"}, + {file = "ruff-0.0.282-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2ca52536e1c7603fe4cbb5ad9dc141df47c3200df782f5ec559364716ea27f96"}, + {file = "ruff-0.0.282-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:aab9ed5bfba6b0a2242a7ec9a72858c802ceeaf0076fe72b2ad455639275f22c"}, + {file = "ruff-0.0.282-py3-none-win32.whl", hash = "sha256:f51bbb64f8f29e444c16d21b269ba82e25f8d536beda3df7c9fe1816297e508e"}, + {file = "ruff-0.0.282-py3-none-win_amd64.whl", hash = "sha256:bd25085c42ebaffe336ed7bda8a0ae7b6c454a5f386ec8b2299503f79bd12bdf"}, + {file = "ruff-0.0.282-py3-none-win_arm64.whl", hash = "sha256:f03fba9621533d67d7ab995847467d78b9337e3697779ef2cea6f1deaee5fbef"}, + {file = "ruff-0.0.282.tar.gz", hash = "sha256:ef677c26bae756e4c98af6d8972da83caea550bc92ffef97a6e939ca5b24ad06"}, ] [[package]] @@ -2696,4 +2696,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "e634f248e2f28160fd669018c4be9cc25b639f6a9c75c5c000386a19acff67db" +content-hash = "41d7ea189a885cd55b363a1a6560e0464b92e5bbb09988ffd547d1da1953dba2" diff --git a/pyproject.toml b/pyproject.toml index 2ec9d8f81f6..af061a7a057 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.282" +ruff = ">=0.0.272,<0.0.283" retry2 = "^0.9.5" [tool.coverage.run] From 907821daaf2d89ebe6c8fc34283c75098d9a4b77 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 2 Aug 2023 08:47:41 -0300 Subject: [PATCH 45/92] fix(metrics): proxy service and namespace attrs to provider (#2910) Co-authored-by: Cavalcante Damascena --- aws_lambda_powertools/metrics/metrics.py | 20 ++++++++++++++++++++ tests/functional/test_metrics.py | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/aws_lambda_powertools/metrics/metrics.py b/aws_lambda_powertools/metrics/metrics.py index d87b7bdd401..d65cb62720a 100644 --- a/aws_lambda_powertools/metrics/metrics.py +++ b/aws_lambda_powertools/metrics/metrics.py @@ -181,6 +181,26 @@ def clear_default_dimensions(self) -> None: def clear_metrics(self) -> None: self.provider.clear_metrics() + # We now allow customers to bring their own instance + # of the AmazonCloudWatchEMFProvider provider + # So we need to define getter/setter for namespace and service properties + # To access these attributes on the provider instance. + @property + def namespace(self): + return self.provider.namespace + + @namespace.setter + def namespace(self, namespace): + self.provider.namespace = namespace + + @property + def service(self): + return self.provider.service + + @service.setter + def service(self, service): + self.provider.service = service + # Maintenance: until v3, we can't afford to break customers. # AmazonCloudWatchEMFProvider has the exact same functionality (non-singleton) diff --git a/tests/functional/test_metrics.py b/tests/functional/test_metrics.py index 1eed6c82294..329ff7064dd 100644 --- a/tests/functional/test_metrics.py +++ b/tests/functional/test_metrics.py @@ -1077,6 +1077,25 @@ def test_clear_default_dimensions(namespace): assert not my_metrics.default_dimensions +def test_get_and_set_namespace_and_service_properties(namespace, service, metrics, capsys): + # GIVEN Metrics instance is initialized without namespace and service + my_metrics = Metrics() + + # WHEN we set service and namespace before flushing the metric + @my_metrics.log_metrics + def lambda_handler(evt, ctx): + my_metrics.namespace = namespace + my_metrics.service = service + for metric in metrics: + my_metrics.add_metric(**metric) + + lambda_handler({}, {}) + invocation = capture_metrics_output(capsys) + + assert service in json.dumps(invocation) + assert namespace in json.dumps(invocation) + + def test_clear_default_dimensions_with_provider(namespace): # GIVEN Metrics is initialized with provider and we persist a set of default dimensions my_provider = AmazonCloudWatchEMFProvider(namespace=namespace) From 6177b9327d7fb684a585cf19df4e4b4a6544b674 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 08:49:46 -0300 Subject: [PATCH 46/92] chore(deps): bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates (#2904) chore(deps): bump the layer-balancer group Bumps the layer-balancer group in /layer/scripts/layer-balancer with 2 updates: [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) and [github.com/aws/aws-sdk-go-v2/service/lambda](https://github.com/aws/aws-sdk-go-v2). Updates `github.com/aws/aws-sdk-go-v2/config` from 1.18.31 to 1.18.32 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.18.31...config/v1.18.32) Updates `github.com/aws/aws-sdk-go-v2/service/lambda` from 1.39.0 to 1.39.1 - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ec2/v1.39.0...service/iot/v1.39.1) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/config dependency-type: direct:production update-type: version-update:semver-patch dependency-group: layer-balancer - dependency-name: github.com/aws/aws-sdk-go-v2/service/lambda dependency-type: direct:production update-type: version-update:semver-patch dependency-group: layer-balancer ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 12 ++++++------ layer/scripts/layer-balancer/go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 15941c60069..157fb24c7ee 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -4,23 +4,23 @@ go 1.18 require ( github.com/aws/aws-sdk-go-v2 v1.20.0 - github.com/aws/aws-sdk-go-v2/config v1.18.31 - github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0 + github.com/aws/aws-sdk-go-v2/config v1.18.32 + github.com/aws/aws-sdk-go-v2/service/lambda v1.39.1 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.30 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.31 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.21.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.13.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 // indirect github.com/aws/smithy-go v1.14.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index abdad5f8003..75da24c2218 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -2,10 +2,10 @@ github.com/aws/aws-sdk-go-v2 v1.20.0 h1:INUDpYLt4oiPOJl0XwZDK2OVAVf0Rzo+MGVTv9f+ github.com/aws/aws-sdk-go-v2 v1.20.0/go.mod h1:uWOr0m0jDsiWw8nnXiqZ+YG6LdvAlGYDLLf2NmHZoy4= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 h1:/MS8AzqYNAhhRNalOmxUvYs8VEbNGifTnzhPFdcRQkQ= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11/go.mod h1:va22++AdXht4ccO3kH2SHkHHYvZ2G9Utz+CXKmm2CaU= -github.com/aws/aws-sdk-go-v2/config v1.18.31 h1:CcacHsJjsPtHpe1MaopwPddUErmLnl+X77+7n4G2KkY= -github.com/aws/aws-sdk-go-v2/config v1.18.31/go.mod h1:pnSeuahFFvtScCHy0INXLxJ4N8H7KncD5u6A48bx3/8= -github.com/aws/aws-sdk-go-v2/credentials v1.13.30 h1:4pt4sI4OwXrrWUGuGr5NEb2g+4IBUB/I2BVj0t2Ak7Q= -github.com/aws/aws-sdk-go-v2/credentials v1.13.30/go.mod h1:Scpo/dGUdxAtRKsNCaXMXONnl3gvvugbXVldy5Fz2DQ= +github.com/aws/aws-sdk-go-v2/config v1.18.32 h1:tqEOvkbTxwEV7hToRcJ1xZRjcATqwDVsWbAscgRKyNI= +github.com/aws/aws-sdk-go-v2/config v1.18.32/go.mod h1:U3ZF0fQRRA4gnbn9GGvOWLoT2EzzZfAWeKwnVrm1rDc= +github.com/aws/aws-sdk-go-v2/credentials v1.13.31 h1:vJyON3lG7R8VOErpJJBclBADiWTwzcwdkQpTKx8D2sk= +github.com/aws/aws-sdk-go-v2/credentials v1.13.31/go.mod h1:T4sESjBtY2lNxLgkIASmeP57b5j7hTQqCbqG0tWnxC4= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 h1:X3H6+SU21x+76LRglk21dFRgMTJMa5QcpW+SqUf5BBg= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7/go.mod h1:3we0V09SwcJBzNlnyovrR2wWJhWmVdqAsmVs4uronv8= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 h1:zr/gxAZkMcvP71ZhQOcvdm8ReLjFgIXnIn0fw5AM7mo= @@ -16,14 +16,14 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 h1:+i1DOFrW3YZ3apE45tCal9+aDKK github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38/go.mod h1:1/jLp0OgOaWIetycOmycW+vYTYgTZFPttJQRgsI1PoU= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31 h1:auGDJ0aLZahF5SPvkJ6WcUuX7iQ7kyl2MamV7Tm8QBk= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31/go.mod h1:3+lloe3sZuBQw1aBc5MyndvodzQlyqCZ7x1QPDHaWP4= -github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0 h1:CDDjp86If1TkvURnNMWcYZpbG+WAGdfO7AWlrwWJ3dk= -github.com/aws/aws-sdk-go-v2/service/lambda v1.39.0/go.mod h1:MiY958jauOEVweMj4Xxa81B45wTg/6ewgp3XeCLV+hg= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.0 h1:agnjK56/1jtGPehxV8QZ/AYHV++pEfl7CpYbWjHjBDc= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.0/go.mod h1:TC9BubuFMVScIU+TLKamO6VZiYTkYoEHqlSQwAe2omw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.0 h1:g0Rr6COTBEaIG9TFQ0GmRkPWOGuDfySGSq2PlMcclrY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.0/go.mod h1:XO/VcyoQ8nKyKfFW/3DMsRQXsfh/052tHTWmg3xBXRg= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.0 h1:HI1YIL5Q9FtucxF5tcNpzCEyLnkeUcqg6xtOx8u09S4= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.0/go.mod h1:G8SbvL0rFk4WOJroU8tKBczhsbhj2p/YY7qeJezJ3CI= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.1 h1:Lhk8/UeifQgYq422El43CEkICp1QHiLSKIz9W4Dygdc= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.1/go.mod h1:MiY958jauOEVweMj4Xxa81B45wTg/6ewgp3XeCLV+hg= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.1 h1:DSNpSbfEgFXRV+IfEcKE5kTbqxm+MeF5WgyeRlsLnHY= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.1/go.mod h1:TC9BubuFMVScIU+TLKamO6VZiYTkYoEHqlSQwAe2omw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1 h1:hd0SKLMdOL/Sl6Z0np1PX9LeH2gqNtBe0MhTedA8MGI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1/go.mod h1:XO/VcyoQ8nKyKfFW/3DMsRQXsfh/052tHTWmg3xBXRg= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 h1:pAOJj+80tC8sPVgSDHzMYD6KLWsaLQ1kZw31PTeORbs= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.1/go.mod h1:G8SbvL0rFk4WOJroU8tKBczhsbhj2p/YY7qeJezJ3CI= github.com/aws/smithy-go v1.14.0 h1:+X90sB94fizKjDmwb4vyl2cTTPXTE5E2G/1mjByb0io= github.com/aws/smithy-go v1.14.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From 6df9b1df0b32d776ca600c1b6354859f64fb79eb Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 2 Aug 2023 14:08:32 +0200 Subject: [PATCH 47/92] refactor(e2e): support fail fast in get_lambda_response (#2912) --- .../idempotency/test_idempotency_dynamodb.py | 26 +++-- tests/e2e/utils/data_builder/traces.py | 2 +- tests/e2e/utils/data_fetcher/common.py | 94 ++++++++++++++++++- tests/e2e/utils/functions.py | 32 ------- 4 files changed, 110 insertions(+), 44 deletions(-) delete mode 100644 tests/e2e/utils/functions.py diff --git a/tests/e2e/idempotency/test_idempotency_dynamodb.py b/tests/e2e/idempotency/test_idempotency_dynamodb.py index a374f763bd4..1d61cb69f9f 100644 --- a/tests/e2e/idempotency/test_idempotency_dynamodb.py +++ b/tests/e2e/idempotency/test_idempotency_dynamodb.py @@ -4,7 +4,7 @@ import pytest from tests.e2e.utils import data_fetcher -from tests.e2e.utils.functions import execute_lambdas_in_parallel +from tests.e2e.utils.data_fetcher.common import GetLambdaResponseOptions, get_lambda_response_in_parallel @pytest.fixture @@ -73,14 +73,21 @@ def test_ttl_caching_expiration_idempotency(ttl_cache_expiration_handler_fn_arn: @pytest.mark.xdist_group(name="idempotency") def test_ttl_caching_timeout_idempotency(ttl_cache_timeout_handler_fn_arn: str): # GIVEN - payload_timeout_execution = json.dumps({"sleep": 5, "message": "Powertools for AWS Lambda (Python) - TTL 1s"}) - payload_working_execution = json.dumps({"sleep": 0, "message": "Powertools for AWS Lambda (Python) - TTL 1s"}) + payload_timeout_execution = json.dumps( + {"sleep": 5, "message": "Powertools for AWS Lambda (Python) - TTL 1s"}, + sort_keys=True, + ) + payload_working_execution = json.dumps( + {"sleep": 0, "message": "Powertools for AWS Lambda (Python) - TTL 1s"}, + sort_keys=True, + ) # WHEN # first call should fail due to timeout execution_with_timeout, _ = data_fetcher.get_lambda_response( lambda_arn=ttl_cache_timeout_handler_fn_arn, payload=payload_timeout_execution, + raise_on_error=False, ) execution_with_timeout_response = execution_with_timeout["Payload"].read().decode("utf-8") @@ -99,12 +106,15 @@ def test_ttl_caching_timeout_idempotency(ttl_cache_timeout_handler_fn_arn: str): @pytest.mark.xdist_group(name="idempotency") def test_parallel_execution_idempotency(parallel_execution_handler_fn_arn: str): # GIVEN - arguments = json.dumps({"message": "Powertools for AWS Lambda (Python) - Parallel execution"}) + payload = json.dumps({"message": "Powertools for AWS Lambda (Python) - Parallel execution"}) - # WHEN - # executing Lambdas in parallel - lambdas_arn = [parallel_execution_handler_fn_arn, parallel_execution_handler_fn_arn] - execution_result_list = execute_lambdas_in_parallel("data_fetcher.get_lambda_response", lambdas_arn, arguments) + invocation_options = [ + GetLambdaResponseOptions(lambda_arn=parallel_execution_handler_fn_arn, payload=payload, raise_on_error=False), + GetLambdaResponseOptions(lambda_arn=parallel_execution_handler_fn_arn, payload=payload, raise_on_error=False), + ] + + # WHEN executing Lambdas in parallel + execution_result_list = get_lambda_response_in_parallel(invocation_options) timeout_execution_response = execution_result_list[0][0]["Payload"].read().decode("utf-8") error_idempotency_execution_response = execution_result_list[1][0]["Payload"].read().decode("utf-8") diff --git a/tests/e2e/utils/data_builder/traces.py b/tests/e2e/utils/data_builder/traces.py index 59350c8ff68..e6356582a30 100644 --- a/tests/e2e/utils/data_builder/traces.py +++ b/tests/e2e/utils/data_builder/traces.py @@ -2,7 +2,7 @@ def build_trace_default_query(function_name: str) -> str: - return f'service("{function_name}")' + return f'service(id(name: "{function_name}"))' def build_put_annotations_input(**annotations: str) -> List[Dict]: diff --git a/tests/e2e/utils/data_fetcher/common.py b/tests/e2e/utils/data_fetcher/common.py index 3bbdaa24e6a..9c251cd6ed2 100644 --- a/tests/e2e/utils/data_fetcher/common.py +++ b/tests/e2e/utils/data_fetcher/common.py @@ -1,24 +1,76 @@ +import functools +import time +from concurrent.futures import Future, ThreadPoolExecutor from datetime import datetime -from typing import Optional, Tuple +from typing import List, Optional, Tuple import boto3 import requests from mypy_boto3_lambda import LambdaClient from mypy_boto3_lambda.type_defs import InvocationResponseTypeDef +from pydantic import BaseModel from requests import Request, Response from requests.exceptions import RequestException from retry import retry +GetLambdaResponse = Tuple[InvocationResponseTypeDef, datetime] + + +class GetLambdaResponseOptions(BaseModel): + lambda_arn: str + payload: Optional[str] = None + client: Optional[LambdaClient] = None + raise_on_error: bool = True + + # Maintenance: Pydantic v2 deprecated it; we should update in v3 + class Config: + arbitrary_types_allowed = True + def get_lambda_response( lambda_arn: str, payload: Optional[str] = None, client: Optional[LambdaClient] = None, -) -> Tuple[InvocationResponseTypeDef, datetime]: + raise_on_error: bool = True, +) -> GetLambdaResponse: + """Invoke function synchronously + + Parameters + ---------- + lambda_arn : str + Lambda function ARN to invoke + payload : Optional[str], optional + JSON payload for Lambda invocation, by default None + client : Optional[LambdaClient], optional + Boto3 Lambda SDK client, by default None + raise_on_error : bool, optional + Whether to raise exception upon invocation error, by default True + + Returns + ------- + Tuple[InvocationResponseTypeDef, datetime] + Function response and approximate execution time + + Raises + ------ + RuntimeError + Function invocation error details + """ client = client or boto3.client("lambda") payload = payload or "" execution_time = datetime.utcnow() - return client.invoke(FunctionName=lambda_arn, InvocationType="RequestResponse", Payload=payload), execution_time + response: InvocationResponseTypeDef = client.invoke( + FunctionName=lambda_arn, + InvocationType="RequestResponse", + Payload=payload, + ) + + has_error = response.get("FunctionError", "") == "Unhandled" + if has_error and raise_on_error: + error_payload = response["Payload"].read().decode() + raise RuntimeError(f"Function failed invocation: {error_payload}") + + return response, execution_time @retry(RequestException, delay=2, jitter=1.5, tries=5) @@ -27,3 +79,39 @@ def get_http_response(request: Request) -> Response: result = session.send(request.prepare()) result.raise_for_status() return result + + +def get_lambda_response_in_parallel( + get_lambda_response_options: List[GetLambdaResponseOptions], +) -> List[GetLambdaResponse]: + """Invoke functions in parallel + + Parameters + ---------- + get_lambda_response_options : List[GetLambdaResponseOptions] + List of options to call get_lambda_response with + + Returns + ------- + List[GetLambdaResponse] + Function responses and approximate execution time + """ + result_list = [] + with ThreadPoolExecutor() as executor: + running_tasks: List[Future] = [] + for options in get_lambda_response_options: + # Sleep 0.5, 1, 1.5, ... seconds between each invocation. This way + # we can guarantee that lambdas are executed in parallel, but they are + # called in the same "order" as they are passed in, thus guaranteeing that + # we can assert on the correct output. + time.sleep(0.5 * len(running_tasks)) + + get_lambda_response_callback = functools.partial(get_lambda_response, **options.dict()) + running_tasks.append( + executor.submit(get_lambda_response_callback), + ) + + executor.shutdown(wait=True) + result_list.extend(running_task.result() for running_task in running_tasks) + + return result_list diff --git a/tests/e2e/utils/functions.py b/tests/e2e/utils/functions.py deleted file mode 100644 index 64135c96aa3..00000000000 --- a/tests/e2e/utils/functions.py +++ /dev/null @@ -1,32 +0,0 @@ -import time -from concurrent.futures import Future, ThreadPoolExecutor -from typing import List - -from tests.e2e.utils import data_fetcher # noqa F401 - - -def execute_lambdas_in_parallel(function_name: str, lambdas_arn: list, arguments: str): - result_list = [] - with ThreadPoolExecutor() as executor: - running_tasks: List[Future] = [] - for arn in lambdas_arn: - # Sleep 0.5, 1, 1.5, ... seconds between each invocation. This way - # we can guarantee that lambdas are executed in parallel, but they are - # called in the same "order" as they are passed in, thus guaranteeing that - # we can assert on the correct output. - time.sleep(0.5 * len(running_tasks)) - running_tasks.append( - executor.submit( - lambda lname, larn, largs: eval(lname)(larn, largs), - function_name, - arn, - arguments, - ), - ) - - executor.shutdown(wait=True) - - for running_task in running_tasks: - result_list.append(running_task.result()) - - return result_list From 9fc6e510f07ff714819ebedd8d1f898c7054c439 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 2 Aug 2023 18:29:18 +0200 Subject: [PATCH 48/92] chore(ci): enable protected branch auditing (#2913) --- .github/workflows/ossf_scorecard.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml index 4d7d2b6fbe4..40d908e8674 100644 --- a/.github/workflows/ossf_scorecard.yml +++ b/.github/workflows/ossf_scorecard.yml @@ -15,6 +15,7 @@ jobs: analysis: name: Scorecard analysis runs-on: ubuntu-latest + environment: scorecard permissions: security-events: write # update code-scanning dashboard id-token: write # confirm org+repo identity before publish results @@ -31,6 +32,7 @@ jobs: results_file: results.sarif results_format: sarif publish_results: true # publish to OSSF Scorecard REST API + repo_token: ${{ secrets.SCORECARD_TOKEN }} # read-only fine-grained token to read branch protection settings - name: "Upload results" uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 From cf05c88354a30206616adfaf26f855b095664d29 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Wed, 2 Aug 2023 18:38:49 +0200 Subject: [PATCH 49/92] docs(roadmap): update roadmap themes (#2915) --- docs/index.md | 22 ++--- docs/maintainers.md | 2 +- docs/roadmap.md | 137 +++++++++++++++++++++------ docs/tutorial/index.md | 4 +- docs/upgrade.md | 2 +- docs/utilities/idempotency.md | 16 ++-- docs/utilities/middleware_factory.md | 2 +- docs/we_made_this.md | 2 +- mkdocs.yml | 3 + 9 files changed, 137 insertions(+), 53 deletions(-) diff --git a/docs/index.md b/docs/index.md index d0269260711..f44f258cdff 100644 --- a/docs/index.md +++ b/docs/index.md @@ -705,18 +705,18 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai | Environment variable | Description | Utility | Default | | ----------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------- | | **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | `"service_undefined"` | -| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics){target="_blank"} | `None` | -| **POWERTOOLS_TRACE_DISABLED** | Explicitly disables tracing | [Tracing](./core/tracer){target="_blank"} | `false` | -| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer){target="_blank"} | `true` | -| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer){target="_blank"} | `true` | -| **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory){target="_blank"} | `false` | -| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger){target="_blank"} | `false` | -| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger){target="_blank"} | `0` | -| **POWERTOOLS_LOG_DEDUPLICATION_DISABLED** | Disables log deduplication filter protection to use Pytest Live Log feature | [Logging](./core/logger){target="_blank"} | `false` | -| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](./utilities/parameters/#adjusting-cache-ttl){target="_blank"} | `5` | -| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters/#ssmprovider){target="_blank"} | `false` | +| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics.md){target="_blank"} | `None` | +| **POWERTOOLS_TRACE_DISABLED** | Explicitly disables tracing | [Tracing](./core/tracer.md){target="_blank"} | `false` | +| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer.md){target="_blank"} | `true` | +| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer.md){target="_blank"} | `true` | +| **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory.md){target="_blank"} | `false` | +| **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger.md){target="_blank"} | `false` | +| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger.md){target="_blank"} | `0` | +| **POWERTOOLS_LOG_DEDUPLICATION_DISABLED** | Disables log deduplication filter protection to use Pytest Live Log feature | [Logging](./core/logger.md){target="_blank"} | `false` | +| **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](./utilities/parameters.md#adjusting-cache-ttl){target="_blank"} | `5` | +| **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store | [Parameters](./utilities/parameters.md#ssmprovider){target="_blank"} | `false` | | **POWERTOOLS_DEV** | Increases verbosity across utilities | Multiple; see [POWERTOOLS_DEV effect below](#optimizing-for-non-production-environments) | `false` | -| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger){target="_blank"} | `INFO` | +| **LOG_LEVEL** | Sets logging level | [Logging](./core/logger.md){target="_blank"} | `INFO` | ### Optimizing for non-production environments diff --git a/docs/maintainers.md b/docs/maintainers.md index 8f3a1980141..c1fbfbb64d1 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -251,7 +251,7 @@ These are some questions to keep in mind when drafting your first or future rele - Can customers understand at a high level what changed in this release? - Is there a link to the documentation where they can read more about each main change? -- Are there any graphics or [code snippets](carbon.now.sh/) that can enhance readability? +- Are there any graphics or [code snippets](https://carbon.now.sh/) that can enhance readability? - Are we calling out any key contributor(s) to this release? - All contributors are automatically credited, use this as an exceptional case to feature them diff --git a/docs/roadmap.md b/docs/roadmap.md index 6b4807f6ddc..fc8b4441754 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -2,25 +2,56 @@ ## Overview -This is our public roadmap that outlines the high level direction we are working towards, namely [Themes](#themes). We update this document when our priorities change: security and stability is our top priority. +Our public roadmap outlines the high level direction we are working towards, namely [Themes](#themes). We update this document when our priorities change: security and stability is our top priority. -[See our latest list of activities »](https://github.com/orgs/aws-powertools/projects/3?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"} +!!! info "For most up-to-date information, see our [board of activities](https://github.com/orgs/aws-powertools/projects/3/views/2?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"}." ## Themes -!!! info "Operational Excellence is priority number 1." +Operational Excellence is priority number 1. This means bug fixing, stability, security, customer's support, and governance will take precedence above all else. -Themes are key activities maintainers are focusing on, besides bug reports. These are updated periodically and you can find the latest [under Epics in our public board](https://github.com/orgs/aws-powertools/projects/3/views/11?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"}. +**What are themes?** -### Increased end-to-end coverage +They are key activities maintainers are focusing on. These are updated periodically and you can find the latest [under Themes in our public board](https://github.com/orgs/aws-powertools/projects/3/views/11?query=is%3Aopen+sort%3Aupdated-desc){target="_blank"}. -We continue to work on increasing end-to-end coverage for all features. Our main challenge is testing contracts for Lambda Event Sources (Parser, Event Source Data Classes) due to the lack of an official JSON schema. +### Observability providers -Some Lambda Event Sources require clusters (e.g., MSK) leading to additional delays of up to 30m in the end-to-end feedback loop. We need a RFC to start discussing viable options, and whether we should publish JSON Schemas from identified contracts. +We want to extend Tracer, Metrics, and Logger to support any [AWS Lambda certified observability partner](https://go.aws/3HtU6CZ){target="_blank"}, along with OpenTelemetry. -### Observability providers +At launch, we will support Datadog since it's [most requested observability provider](https://github.com/aws-powertools/powertools-lambda-python/issues/1433). OpenTelemetry will be a fast follow-up as we need to decide on a stable solution to cold start penalty. + +!!! tip "Help us identify which observability providers we should integrate next. Open [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE){target="_blank"} or by voting `+1` in existing issues" + +**Major updates** + +- [x] [Document how customers can use any provider with Logger](https://docs.powertools.aws.dev/lambda/python/latest/core/logger/#observability-providers) +- [x] [Extend Metrics to add support for any Provider](https://github.com/aws-powertools/powertools-lambda-python/pull/2194) +- [ ] [Extend Tracer to add support for any Provider](https://github.com/aws-powertools/powertools-lambda-python/issues/2030) +- [ ] Investigate alternative solution to OpenTelemetry cold start performance + +### Sensitive Data Masking + +Data Masking will be a new utility to mask/unmask sensitive data using encryption providers. It's the second most voted feature request (behind [Observability Providers](#observability-providers)). + +**Major updates** -We want to extend Tracer, Metrics, and Logger to support any [observability provider](https://github.com/aws-powertools/powertools-lambda-python/issues/1433){target="_blank"}. We need a RFC to define a contract and to identify two most requested observability providers that we can work with as an initial step. +- [x] [RFC to agree on design and MVP](https://github.com/aws-powertools/powertools-lambda-python/issues/1858) +- [ ] [POC with AWS KMS as the default provider](https://github.com/aws-powertools/powertools-lambda-python/pull/2197) +- [ ] Documentation to guide customers how to bring their own provider (e.g., `ItsDangerous`) + +### Revamp Event Handler + +Event Handler provides lightweight routing for both [**REST**: Amazon API Gateway, Amazon Elastic Load Balancer and AWS Lambda Function URL](./core/event_handler/api_gateway.md), and [**GraphQL**: AWS AppSync](./core/event_handler/appsync.md). + +Based on customers feedback, we want to provide middleware authoring support for cross-cutting concerns. For REST APIs, we are also looking into auto-generate OpenAPI Schemas and a SwaggerUI route. For GraphQL, we are working on supporting batch invocations (N+1 problem) along with partial failure support. + +**Major updates** + +- [x] [Agree on experience for middleware support](https://github.com/aws-powertools/powertools-lambda-python/issues/953#issuecomment-1450223155) +- [x] [RFC to outline initial thoughts on OpenAPI integration](https://github.com/aws-powertools/powertools-lambda-python/issues/2421) +- [ ] MVP for REST middleware +- [ ] MVP for OpenAPI and SwaggerUI +- [ ] [MVP for AppSync Batch invoke and partial failure support](https://github.com/aws-powertools/powertools-lambda-python/pull/1998) ### Lambda Layer in release notes @@ -30,19 +61,69 @@ As of V2, we prioritize Lambda Layers being available before release notes are o This means we have room to include a JSON map for Lambda Layers and facilitate automation for customers wanting the latest version as soon as it's available. -### Strict typing +**Major updates** + +- [x] Create secure mechanism to upload signed assets to GitHub Release Notes +- [ ] Create feature request to agree on JSON structure and asset name + +### Office hours + +We heard from [customers](https://github.com/aws-powertools/powertools-lambda-python#connect){target="_blank"} that Powertools for AWS Lambda and its community can move faster than they are able to catch up. While documentation and release notes take these into account, they notice they don't always know advanced tricks, or what other customers tend to do in similar situations. + +We want to run a monthly office hours to start addressing that, and learn from customers how they're using Powertools and whether or not they need a closer support. + +Timezones being tricky, we plan to experiment with an afternoon slot in Central European that would also cover Middle East, US east coast, and South America. Depending on attendance, we plan to A/B test an Asia friendly one too. + +**Major updates** + +- [ ] Decide whether to use Amazon Chime or Zoom (we had audio setup issues on Discord) + +### Authentication (SigV4) + +[During customers interview](https://github.com/aws-powertools/powertools-lambda-python#connect){target="_blank"}, we hear that signing requests using [AWS SigV4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html){target="_blank"} could be easier. + +Since JWT is a close second, this new utility would cover higher level functions to sign and verify requests more easily. + +**Major updates** + +- [ ] RFC to outline challenges, alternative solutions and desired experience +- [ ] MVP based off RFC + +### Enhanced operational metrics + +[Through customers interview](https://github.com/aws-powertools/powertools-lambda-python#connect){target="_blank"}, [Discord](https://discord.gg/B8zZKbbyET){target="_blank" rel="nofollow"}, and [1:1 customer enablement](https://github.com/aws-powertools/powertools-lambda-python#connect){target="_blank"}, we noticed customers often create the same set of custom operational metrics. + +We want to make this easier by extending certain utilities to accept a `metrics` instance and metrics configuration (what metrics to create). It would be opt-in due to costs associated with creating metrics. + +!!! question "Got ideas for custom metrics? Open up a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE)"{target="_blank"} + +**Major updates** + +- [ ] RFC to outline metrics for Batch (_e.g., Failed items, Batch size_) +- [ ] RFC to outline metrics for Feature flags (_e.g., matched rules_) +- [ ] RFC to outline metrics for Event Handler (_e.g., validation errors_ ) +- [ ] RFC to outline metrics for Idempotency (_e.g., cache hit_) + +### V3 -We want to enable MyPy strict mode against the code base. We need a RFC to identify most critical areas to start, and do so gradually as to not impact new features and enhancements in parallel. +With Python 3.7 reaching [end-of-life in AWS Lambda by the end of the year](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html), we want to plan some breaking changes. As always, we plan on having ample notice, a detailed upgrade guide, and keep breaking changes to a minimum to ease transition (e.g., it took ~7 months from v2 to surpass v1 downloads). -This also means bringing `typing-extensions` as a runtime dependency to ensure complete coverage across all Python versions. Future wise, we might be able to experiment with [MyPyC](https://github.com/mypyc/mypyc){target="_blank" rel="nofollow"} to compile less performing parts of the code base as a C-Extension. +For example, these are on our mind but not settled yet until we have a public tracker to discuss what these means in detail. -### New utilities - -With V2 launched, we want to resume working on new utilities, specifically but not limited to the most commonly asked: **(1)** [Sensitive Data Masking](https://github.com/aws-powertools/powertools-lambda-python/issues/1173){target="_blank"}, **(2)** [Integration/End-to-end Testing](https://github.com/aws-powertools/powertools-lambda-python/issues/1169){target="_blank"}, and **(3)** [Event Bridge](https://github.com/aws-powertools/powertools-lambda-python/issues/1168){target="_blank"}. +- **Parser**: Drop Pydantic v1 +- **Parser**: Deserialize Amazon DynamoDB data types automatically (like Event Source Data Classes) +- **Parameters**: Increase default `max_age` for `get_secret` +- **Event Source Data Classes**: Return sane defaults for any property that has `Optional[]` returns +- **Python 3.7 EOL**: Update PyPi and Layers to only support 3.8 +- **Upgrade tool**: Consider building a CST (Concrete Syntax Tree) tool to ease certain upgrade actions like `pyupgrade` and `django-upgrade` +- **Batch**: Stop at first error for Amazon DynamoDB Streams and Amazon Kinesis Data Streams (e.g., `stop_on_failure=True`) -### Open iteration planning +**Major updates** -We want to experiment running a bi-weekly audio channel on [Discord](https://discord.gg/B8zZKbbyET){target="_blank" rel="nofollow"} to help us prioritize backlog in real-time. Depending on attendance, we might switch to run an office hours instead. +- [ ] Create an issue to track breaking changes we consider making +- [ ] Create a v3 branch to allow early experimentation +- [ ] Create workflows to allow pre-releases +- [ ] Create a mechanism to keep ideas for breaking change somewhere regardless of v3 ## Roadmap status definition @@ -56,11 +137,11 @@ graph LR Within our [public board](https://github.com/orgs/aws-powertools/projects/3/views/1?query=is%3Aopen+sort%3Aupdated-desc){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. +- **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. @@ -82,12 +163,12 @@ graph LR Our end-to-end mechanism follows four major steps: -* **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&template=feature_request.yml&title=Feature+request%3A+TITLE){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 issue template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE){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. +- **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&template=feature_request.yml&title=Feature+request%3A+TITLE){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 issue template](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=RFC%2Ctriage&template=rfc.yml&title=RFC%3A+TITLE){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](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/MAINTAINERS.md){target="_blank"} document to understand how we triage issues and pull requests, labels and governance." diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md index ae4fd4a7181..bf9afdaf70b 100644 --- a/docs/tutorial/index.md +++ b/docs/tutorial/index.md @@ -226,7 +226,7 @@ For this to work, we could create a new Lambda function to handle incoming reque We could group similar routes and intents, separate read and write operations resulting in fewer functions. It doesn't address the boilerplate routing code, but maybe it will be easier to add additional URLs. ???+ info "Info: You might be already asking yourself about mono vs micro-functions" - If you want a more detailed explanation of these two approaches, head over to the [trade-offs on each approach](../core/event_handler/api_gateway/#considerations){target="_blank"} later. + If you want a more detailed explanation of these two approaches, head over to the [trade-offs on each approach](../core/event_handler/api_gateway.md#considerations){target="_blank"} later. A first attempt at the routing logic might look similar to the following code snippet. @@ -773,7 +773,7 @@ Another subtle difference is that you can now run your Lambda functions and unit Powertools for AWS Lambda (Python) optimizes for Lambda compute environment. As such, we add these and other common approaches to accelerate your development, so you don't worry about implementing every cross-cutting concern. ???+ tip - You can [opt-out some of these behaviours](../core/tracer/#advanced){target="_blank"} like disabling response capturing, explicitly patching only X modules, etc. + You can [opt-out some of these behaviours](../core/tracer.md#advanced){target="_blank"} like disabling response capturing, explicitly patching only X modules, etc. Repeat the process of building, deploying, and invoking your application via the API endpoint. Within the [AWS X-Ray Console](https://console.aws.amazon.com/xray/home#/traces/){target="_blank"}, you should see a similar view: diff --git a/docs/upgrade.md b/docs/upgrade.md index 064c6a9657a..d9602da1a53 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -44,7 +44,7 @@ You can migrate to `BatchProcessor` with the following changes: 1. If you use **`sqs_batch_decorator`**, change to **`batch_processor`** decorator 2. If you use **`PartialSQSProcessor`**, change to **`BatchProcessor`** -3. [Enable **`ReportBatchItemFailures`** in your Lambda Event Source](../utilities/batch#required-resources){target="_blank"} +3. [Enable **`ReportBatchItemFailures`** in your Lambda Event Source](./utilities/batch.md#required-resources){target="_blank"} 4. Change your Lambda Handler to return the new response format === "[Before] Decorator" diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index 1b2128cd7f0..6e5c47af6fc 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -496,14 +496,14 @@ When using DynamoDB as a persistence layer, you can alter the attribute names by Idempotent decorator can be further configured with **`IdempotencyConfig`** as seen in the previous example. These are the available options for further configuration -| Parameter | Default | Description | -| ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **event_key_jmespath** | `""` | JMESPath expression to extract the idempotency key from the event record using [built-in functions](/utilities/jmespath_functions){target="_blank"} | -| **payload_validation_jmespath** | `""` | JMESPath expression to validate whether certain parameters have changed in the event while the event payload | -| **raise_on_no_idempotency_key** | `False` | Raise exception if no idempotency key was found in the request | -| **expires_after_seconds** | 3600 | The number of seconds to wait before a record is expired | -| **use_local_cache** | `False` | Whether to locally cache idempotency results | -| **local_cache_max_items** | 256 | Max number of items to store in local cache | +| Parameter | Default | Description | +| ------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **event_key_jmespath** | `""` | JMESPath expression to extract the idempotency key from the event record using [built-in functions](./jmespath_functions.md#built-in-jmespath-functions){target="_blank"} | +| **payload_validation_jmespath** | `""` | JMESPath expression to validate whether certain parameters have changed in the event while the event payload | +| **raise_on_no_idempotency_key** | `False` | Raise exception if no idempotency key was found in the request | +| **expires_after_seconds** | 3600 | The number of seconds to wait before a record is expired | +| **use_local_cache** | `False` | Whether to locally cache idempotency results | +| **local_cache_max_items** | 256 | Max number of items to store in local cache | | **hash_function** | `md5` | Function to use for calculating hashes, as provided by [hashlib](https://docs.python.org/3/library/hashlib.html){target="_blank" rel="nofollow"} in the standard library. | ### Handling concurrent executions with the same payload diff --git a/docs/utilities/middleware_factory.md b/docs/utilities/middleware_factory.md index 41670025b1e..6b0847ddb47 100644 --- a/docs/utilities/middleware_factory.md +++ b/docs/utilities/middleware_factory.md @@ -92,7 +92,7 @@ If you are making use of [Tracer](../core/tracer.md){target="_blank"}, you can t This makes use of an existing Tracer instance that you may have initialized anywhere in your code. ???+ warning - You must [enable Active Tracing](../core/tracer/#permissions){target="_blank"} in your Lambda function when using this feature, otherwise Lambda cannot send traces to XRay. + You must [enable Active Tracing](../core/tracer.md#permissions){target="_blank"} in your Lambda function when using this feature, otherwise Lambda cannot send traces to XRay. === "getting_started_middleware_tracer_function.py" ```python hl_lines="8 14 15 36" diff --git a/docs/we_made_this.md b/docs/we_made_this.md index a2f3d0e8022..a1229ec99aa 100644 --- a/docs/we_made_this.md +++ b/docs/we_made_this.md @@ -82,7 +82,7 @@ This article walks through how CyberArk uses Powertools to implement Feature Fla ### Designing for Idempotency -> **Author: [Valentin Dreismann](linkedin.com/in/valentin-dreismann-69694b16a){target="_blank" rel="nofollow"}** :material-linkedin: +> **Author: [Valentin Dreismann](https://linkedin.com/in/valentin-dreismann-69694b16a){target="_blank" rel="nofollow"}** :material-linkedin: This article outlines the importance of idempotency, key considerations and trade-offs when implementing in your systems. diff --git a/mkdocs.yml b/mkdocs.yml index 77322a535be..49bf5a347e5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,6 +11,7 @@ nav: - API reference: api/" target="_blank - Upgrade guide: upgrade.md - We Made This (Community): we_made_this.md + - Roadmap: roadmap.md - Features: - core/tracer.md - core/logger.md @@ -95,6 +96,8 @@ markdown_extensions: - name: mermaid class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tasklist: + custom_checkbox: true copyright: Copyright © 2023 Amazon Web Services From 4ff9ff17922d27a967c8946e98873d4e35d97ca3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:40:27 +0200 Subject: [PATCH 50/92] chore(ci): changelog rebuild (#2918) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08b6605bcbc..566925ab061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ ## Bug Fixes * **logger:** strip xray_trace_id when explicitly disabled ([#2852](https://github.com/aws-powertools/powertools-lambda-python/issues/2852)) +* **metrics:** proxy service and namespace attrs to provider ([#2910](https://github.com/aws-powertools/powertools-lambda-python/issues/2910)) + +## Code Refactoring + +* **e2e:** support fail fast in get_lambda_response ([#2912](https://github.com/aws-powertools/powertools-lambda-python/issues/2912)) ## Documentation @@ -14,6 +19,7 @@ * **batch:** new visuals and error handling section ([#2857](https://github.com/aws-powertools/powertools-lambda-python/issues/2857)) * **navigation:** remove nofollow attribute for internal links ([#2867](https://github.com/aws-powertools/powertools-lambda-python/issues/2867)) * **navigation:** add nofollow attribute ([#2842](https://github.com/aws-powertools/powertools-lambda-python/issues/2842)) +* **roadmap:** update roadmap themes ([#2915](https://github.com/aws-powertools/powertools-lambda-python/issues/2915)) * **tutorial:** add support for Python 3.11 ([#2860](https://github.com/aws-powertools/powertools-lambda-python/issues/2860)) ## Features @@ -23,34 +29,37 @@ ## Maintenance * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) * **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) +* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) -* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) -* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) -* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) -* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) +* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) From 832df6f11278d87d9083bcfa8238c401e513e33d Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Fri, 4 Aug 2023 09:52:25 -0300 Subject: [PATCH 51/92] feat(layers): add new comercial region Israel(Tel Aviv) (#2907) Co-authored-by: Cavalcante Damascena Co-authored-by: Heitor Lessa --- .github/workflows/reusable_deploy_v2_layer_stack.yml | 2 ++ docs/index.md | 1 + layer/scripts/layer-balancer/main.go | 1 + 3 files changed, 4 insertions(+) diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index dc2e143a778..ef06b82518e 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -120,6 +120,8 @@ jobs: has_arm64_support: "true" - region: "eu-west-3" has_arm64_support: "true" + - region: "il-central-1" + has_arm64_support: "false" - region: "me-central-1" has_arm64_support: "false" - region: "me-south-1" diff --git a/docs/index.md b/docs/index.md index f44f258cdff..54a0f2c58ad 100644 --- a/docs/index.md +++ b/docs/index.md @@ -100,6 +100,7 @@ You can include Powertools for AWS Lambda (Python) Lambda Layer using [AWS Lambd | `eu-west-1` | [arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | | `eu-west-2` | [arn:aws:lambda:eu-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | | `eu-west-3` | [arn:aws:lambda:eu-west-3:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | + | `il-central-1` | [arn:aws:lambda:il-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | | `me-central-1` | [arn:aws:lambda:me-central-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | | `me-south-1` | [arn:aws:lambda:me-south-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | | `sa-east-1` | [arn:aws:lambda:sa-east-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:40](#){: .copyMe}:clipboard: | diff --git a/layer/scripts/layer-balancer/main.go b/layer/scripts/layer-balancer/main.go index 0a800a5c524..a4b28fd0545 100644 --- a/layer/scripts/layer-balancer/main.go +++ b/layer/scripts/layer-balancer/main.go @@ -79,6 +79,7 @@ var singleArchitectureRegions = []string{ "eu-central-2", "eu-south-2", "me-central-1", + "il-central-1", } // getLayerVersion returns the latest version of a layer in a region From 2be3071a800f90256f11046feaebc0cae786768e Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Fri, 4 Aug 2023 15:03:25 +0200 Subject: [PATCH 52/92] chore(docs): disable line length rule using older syntax (#2920) * fix(parameters): make cache aware of single vs multiple calls Signed-off-by: heitorlessa * chore: cleanup, add test for single and nested Signed-off-by: heitorlessa * docs: disable line length rule using older syntax Signed-off-by: heitorlessa --------- Signed-off-by: heitorlessa Co-authored-by: Leandro Damascena --- docs/maintainers.md | 3 ++- docs/utilities/validation.md | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/maintainers.md b/docs/maintainers.md index c1fbfbb64d1..4fd4f109a33 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -289,8 +289,9 @@ Add integration checks that validate pull requests and pushes to ease the burden ### Negative Impact on the Project - + Actions that negatively impact the project will be handled by the admins, in coordination with other maintainers, in balance with the urgency of the issue. Examples would be [Code of Conduct](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/CODE_OF_CONDUCT.md){target="_blank"} violations, deliberate harmful or malicious actions, spam, monopolization, and security risks. + ### Becoming a maintainer diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 7d822cf4b4c..1b569ddc14c 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -112,8 +112,9 @@ Here is a sample custom EventBridge event, where we only validate what's inside ```json --8<-- "examples/validation/src/getting_started_validator_unwrapping_payload.json" ``` - + This is quite powerful because you can use JMESPath Query language to extract records from [arrays](https://jmespath.org/tutorial.html#list-and-slice-projections){target="_blank" rel="nofollow"}, combine [pipe](https://jmespath.org/tutorial.html#pipe-expressions){target="_blank" rel="nofollow"} and [function expressions](https://jmespath.org/tutorial.html#functions){target="_blank" rel="nofollow"}. + When combined, these features allow you to extract what you need before validating the actual payload. @@ -141,16 +142,16 @@ We provide built-in envelopes to easily extract the payload from popular event s Here is a handy table with built-in envelopes along with their JMESPath expressions in case you want to build your own. -| Envelope | JMESPath expression | -| --------------------------------- | ------------------------------------------------------------------------ | -| **`API_GATEWAY_HTTP`** | `powertools_json(body)` | -| **`API_GATEWAY_REST`** | `powertools_json(body)` | -| **`CLOUDWATCH_EVENTS_SCHEDULED`** | `detail` | -| **`CLOUDWATCH_LOGS`** | `awslogs.powertools_base64_gzip(data) | powertools_json(@).logEvents[*]` | -| **`EVENTBRIDGE`** | `detail` | -| **`KINESIS_DATA_STREAM`** | `Records[*].kinesis.powertools_json(powertools_base64(data))` | -| **`SNS`** | `Records[0].Sns.Message | powertools_json(@)` | -| **`SQS`** | `Records[*].powertools_json(body)` | +| Envelope | JMESPath expression | +| --------------------------------- | ------------------------------------------------------------- | +| **`API_GATEWAY_HTTP`** | `powertools_json(body)` | +| **`API_GATEWAY_REST`** | `powertools_json(body)` | +| **`CLOUDWATCH_EVENTS_SCHEDULED`** | `detail` | +| **`CLOUDWATCH_LOGS`** | `awslogs.powertools_base64_gzip(data) | powertools_json(@).logEvents[*]` | +| **`EVENTBRIDGE`** | `detail` | +| **`KINESIS_DATA_STREAM`** | `Records[*].kinesis.powertools_json(powertools_base64(data))` | +| **`SNS`** | `Records[0].Sns.Message | powertools_json(@)` | +| **`SQS`** | `Records[*].powertools_json(body)` | ## Advanced From 4d2c9c4f8086d7a9a90a3a32645693fd73857b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivica=20Kolenka=C5=A1?= Date: Fri, 4 Aug 2023 18:32:14 +0200 Subject: [PATCH 53/92] chore(maintenance): enables publishing docs and changelog, running e2e tests only in the main repository (#2924) --- .github/workflows/reusable_publish_changelog.yml | 1 + .github/workflows/reusable_publish_docs.yml | 1 + .github/workflows/run-e2e-tests.yml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reusable_publish_changelog.yml b/.github/workflows/reusable_publish_changelog.yml index 1df1ceb5953..0a678d9ee7d 100644 --- a/.github/workflows/reusable_publish_changelog.yml +++ b/.github/workflows/reusable_publish_changelog.yml @@ -15,6 +15,7 @@ permissions: jobs: publish_changelog: + if: github.repository == 'aws-powertools/powertools-lambda-python' # Force Github action to run only a single job at a time (based on the group name) # This is to prevent race-condition and inconsistencies with changelog push concurrency: diff --git a/.github/workflows/reusable_publish_docs.yml b/.github/workflows/reusable_publish_docs.yml index 83f5198f1a9..8d86664d87e 100644 --- a/.github/workflows/reusable_publish_docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -32,6 +32,7 @@ permissions: jobs: publish_docs: + if: github.repository == 'aws-powertools/powertools-lambda-python' # Force Github action to run only a single job at a time (based on the group name) # This is to prevent "race-condition" in publishing a new version of doc to `gh-pages` concurrency: diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index af6e884041b..94e5f02e5c7 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -48,7 +48,7 @@ jobs: fail-fast: false # needed so if a version fails, the others will still be able to complete and cleanup matrix: version: ["3.7", "3.8", "3.9", "3.10", "3.11"] - if: ${{ github.actor != 'dependabot[bot]' }} + if: ${{ github.actor != 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-python' }} steps: - name: "Checkout" uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 From 7360793c8196127b60500f98cf3119baad002358 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Aug 2023 17:41:48 -0300 Subject: [PATCH 54/92] chore(deps): bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 (#2927) chore(deps): bump slsa-framework/slsa-github-generator Bumps [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/slsa-framework/slsa-github-generator/releases) - [Changelog](https://github.com/slsa-framework/slsa-github-generator/blob/main/CHANGELOG.md) - [Commits](https://github.com/slsa-framework/slsa-github-generator/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: slsa-framework/slsa-github-generator 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> --- .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 351da7f67b7..465ee561c4a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -206,7 +206,7 @@ jobs: # NOTE: provenance fails if we use action pinning... it's a Github limitation # because SLSA needs to trace & attest it came from a given branch; pinning doesn't expose that information # https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/generic/README.md#referencing-the-slsa-generator - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.7.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.8.0 with: base64-subjects: ${{ needs.build.outputs.attestation_hashes }} upload-assets: false # we upload its attestation in create_tag job, otherwise it creates a new release From 663c14069417c31cfbaef8375d5fc1e9d680fd0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:32:48 -0300 Subject: [PATCH 55/92] chore(deps-dev): bump the boto-typing group with 4 updates (#2928) Bumps the boto-typing group with 4 updates: [mypy-boto3-cloudformation](https://github.com/youtype/mypy_boto3_builder), [mypy-boto3-dynamodb](https://github.com/youtype/mypy_boto3_builder), [mypy-boto3-lambda](https://github.com/youtype/mypy_boto3_builder) and [mypy-boto3-s3](https://github.com/youtype/mypy_boto3_builder). Updates `mypy-boto3-cloudformation` from 1.28.16 to 1.28.19 - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) Updates `mypy-boto3-dynamodb` from 1.28.16 to 1.28.19 - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) Updates `mypy-boto3-lambda` from 1.28.16 to 1.28.19 - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) Updates `mypy-boto3-s3` from 1.28.16 to 1.28.19 - [Release notes](https://github.com/youtype/mypy_boto3_builder/releases) - [Commits](https://github.com/youtype/mypy_boto3_builder/commits) --- updated-dependencies: - dependency-name: mypy-boto3-cloudformation dependency-type: direct:development update-type: version-update:semver-patch dependency-group: boto-typing - dependency-name: mypy-boto3-dynamodb dependency-type: direct:development update-type: version-update:semver-patch dependency-group: boto-typing - dependency-name: mypy-boto3-lambda dependency-type: direct:development update-type: version-update:semver-patch dependency-group: boto-typing - dependency-name: mypy-boto3-s3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: boto-typing ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 34 +++++++++++++++++----------------- pyproject.toml | 8 ++++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/poetry.lock b/poetry.lock index d8e044fa292..4806ea5d188 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1460,13 +1460,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudformation" -version = "1.28.16" -description = "Type annotations for boto3.CloudFormation 1.28.16 service generated with mypy-boto3-builder 7.17.1" +version = "1.28.19" +description = "Type annotations for boto3.CloudFormation 1.28.19 service generated with mypy-boto3-builder 7.17.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudformation-1.28.16.tar.gz", hash = "sha256:a5202db1ea76aa499a27b971745e0130e5cb88c2b323c48cca30cd01713d963a"}, - {file = "mypy_boto3_cloudformation-1.28.16-py3-none-any.whl", hash = "sha256:228cb6e9096f64d36abd912c34e465545ff848bb837498112dc30235ca19750c"}, + {file = "mypy-boto3-cloudformation-1.28.19.tar.gz", hash = "sha256:efb08a2a6d7c744d0d8d60f04514c531355aa7972b53f025d9e08e3adf3a5504"}, + {file = "mypy_boto3_cloudformation-1.28.19-py3-none-any.whl", hash = "sha256:aadf78eb2f2e3b2e83a4844a80d0c5d0d72ad11c453a11efdd28b0c309b05bf6"}, ] [package.dependencies] @@ -1488,13 +1488,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.28.16" -description = "Type annotations for boto3.DynamoDB 1.28.16 service generated with mypy-boto3-builder 7.17.1" +version = "1.28.19" +description = "Type annotations for boto3.DynamoDB 1.28.19 service generated with mypy-boto3-builder 7.17.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.28.16.tar.gz", hash = "sha256:540fad881e240cb624b6e22b4461048c31cfb9ef1da6ae26ca70d1f385605930"}, - {file = "mypy_boto3_dynamodb-1.28.16-py3-none-any.whl", hash = "sha256:e9be4037aaad101689aae080fc3ca9ee8995a4d721235fc5d88aa005e3cf67c2"}, + {file = "mypy-boto3-dynamodb-1.28.19.tar.gz", hash = "sha256:6b9b407c9e2fc73ac5d475a8c98af4e1bea3899e5e74ce00d11cb9c878af761b"}, + {file = "mypy_boto3_dynamodb-1.28.19-py3-none-any.whl", hash = "sha256:a0859c469f46f7e354ae707f1f97bea36746d5538ee851b18d5b61cfb9cf91b9"}, ] [package.dependencies] @@ -1502,13 +1502,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-lambda" -version = "1.28.16" -description = "Type annotations for boto3.Lambda 1.28.16 service generated with mypy-boto3-builder 7.17.1" +version = "1.28.19" +description = "Type annotations for boto3.Lambda 1.28.19 service generated with mypy-boto3-builder 7.17.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-lambda-1.28.16.tar.gz", hash = "sha256:c7c647139e6710da694aba4a644f69f4a06c6e43419168d69cc57f3dc6e5e607"}, - {file = "mypy_boto3_lambda-1.28.16-py3-none-any.whl", hash = "sha256:c1b688c1ea7cbb9b79b8a1dcaaa7459791ae7ebc608490251f58a07edb31170c"}, + {file = "mypy-boto3-lambda-1.28.19.tar.gz", hash = "sha256:955b7702f02f2037ba4c058f6dcebfcce50090ac13c9d031a0052fa9136ec59e"}, + {file = "mypy_boto3_lambda-1.28.19-py3-none-any.whl", hash = "sha256:88582f8ca71bd7a6bbcf8b05155476f0a9dea79630a4da36d367482925241710"}, ] [package.dependencies] @@ -1530,13 +1530,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-s3" -version = "1.28.16" -description = "Type annotations for boto3.S3 1.28.16 service generated with mypy-boto3-builder 7.17.1" +version = "1.28.19" +description = "Type annotations for boto3.S3 1.28.19 service generated with mypy-boto3-builder 7.17.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.28.16.tar.gz", hash = "sha256:4e55fdad729b6e6f45211e354bd1a0a745a565fe9d1e462737f775c28849cfb5"}, - {file = "mypy_boto3_s3-1.28.16-py3-none-any.whl", hash = "sha256:855f7848186c45adbd3c474fec2d75db17f4cd7200c0a2235473250454ec4686"}, + {file = "mypy-boto3-s3-1.28.19.tar.gz", hash = "sha256:b8104b191924d8672068d21d748c0f8ae0b0e1950324cb315ec8a1ceed9d23ac"}, + {file = "mypy_boto3_s3-1.28.19-py3-none-any.whl", hash = "sha256:d3759a8fb004f482565904d788d844eeccf3e03b8fa1b96a0f82ba1527ef4022"}, ] [package.dependencies] @@ -2696,4 +2696,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "41d7ea189a885cd55b363a1a6560e0464b92e5bbb09988ffd547d1da1953dba2" +content-hash = "6a98f15c7d5cb443e2a717298243d990a81944f2646b767aedee60962b8fc953" diff --git a/pyproject.toml b/pyproject.toml index af061a7a057..ece1830e734 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,14 +57,14 @@ aws-cdk-lib = "^2.88.0" "aws-cdk.aws-apigatewayv2-authorizers-alpha" = "^2.38.1-alpha.0" pytest-benchmark = "^4.0.0" mypy-boto3-appconfig = "^1.28.16" -mypy-boto3-cloudformation = "^1.28.16" +mypy-boto3-cloudformation = "^1.28.19" mypy-boto3-cloudwatch = "^1.28.16" -mypy-boto3-dynamodb = "^1.28.16" -mypy-boto3-lambda = "^1.28.16" +mypy-boto3-dynamodb = "^1.28.19" +mypy-boto3-lambda = "^1.28.19" mypy-boto3-logs = "^1.28.16" mypy-boto3-secretsmanager = "^1.28.16" mypy-boto3-ssm = "^1.28.16" -mypy-boto3-s3 = "^1.28.16" +mypy-boto3-s3 = "^1.28.19" mypy-boto3-xray = "^1.28.16" types-requests = "^2.31.0" typing-extensions = "^4.6.2" From dd47f4c4c21f5a533ac309c6fb9ea33ee07ee695 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:07:27 +0200 Subject: [PATCH 56/92] chore(ci): changelog rebuild (#2931) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 566925ab061..ae644074b05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,42 +24,47 @@ ## Features +* **layers:** add new comercial region Israel(Tel Aviv) ([#2907](https://github.com/aws-powertools/powertools-lambda-python/issues/2907)) * **metrics:** support to bring your own metrics provider ([#2194](https://github.com/aws-powertools/powertools-lambda-python/issues/2194)) ## Maintenance -* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) -* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) +* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) +* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) * **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) +* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) +* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) -* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) -* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) +* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) +* **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) +* **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From c8c9572203a049bb253ce3e259215b23aa0ac565 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 22:47:34 +0100 Subject: [PATCH 57/92] chore(deps): bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates (#2933) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 28 +++++++-------- layer/scripts/layer-balancer/go.sum | 56 ++++++++++++++--------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 157fb24c7ee..5a6f45392eb 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -3,24 +3,24 @@ module layerbalancer go 1.18 require ( - github.com/aws/aws-sdk-go-v2 v1.20.0 - github.com/aws/aws-sdk-go-v2/config v1.18.32 - github.com/aws/aws-sdk-go-v2/service/lambda v1.39.1 + github.com/aws/aws-sdk-go-v2 v1.20.1 + github.com/aws/aws-sdk-go-v2/config v1.18.33 + github.com/aws/aws-sdk-go-v2/service/lambda v1.39.2 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) require ( - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.31 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.13.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 // indirect - github.com/aws/smithy-go v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.32 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.21.2 // indirect + github.com/aws/smithy-go v1.14.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 75da24c2218..9b7f76ab4d1 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,31 +1,31 @@ -github.com/aws/aws-sdk-go-v2 v1.20.0 h1:INUDpYLt4oiPOJl0XwZDK2OVAVf0Rzo+MGVTv9f+gy8= -github.com/aws/aws-sdk-go-v2 v1.20.0/go.mod h1:uWOr0m0jDsiWw8nnXiqZ+YG6LdvAlGYDLLf2NmHZoy4= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11 h1:/MS8AzqYNAhhRNalOmxUvYs8VEbNGifTnzhPFdcRQkQ= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.11/go.mod h1:va22++AdXht4ccO3kH2SHkHHYvZ2G9Utz+CXKmm2CaU= -github.com/aws/aws-sdk-go-v2/config v1.18.32 h1:tqEOvkbTxwEV7hToRcJ1xZRjcATqwDVsWbAscgRKyNI= -github.com/aws/aws-sdk-go-v2/config v1.18.32/go.mod h1:U3ZF0fQRRA4gnbn9GGvOWLoT2EzzZfAWeKwnVrm1rDc= -github.com/aws/aws-sdk-go-v2/credentials v1.13.31 h1:vJyON3lG7R8VOErpJJBclBADiWTwzcwdkQpTKx8D2sk= -github.com/aws/aws-sdk-go-v2/credentials v1.13.31/go.mod h1:T4sESjBtY2lNxLgkIASmeP57b5j7hTQqCbqG0tWnxC4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7 h1:X3H6+SU21x+76LRglk21dFRgMTJMa5QcpW+SqUf5BBg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.7/go.mod h1:3we0V09SwcJBzNlnyovrR2wWJhWmVdqAsmVs4uronv8= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37 h1:zr/gxAZkMcvP71ZhQOcvdm8ReLjFgIXnIn0fw5AM7mo= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.37/go.mod h1:Pdn4j43v49Kk6+82spO3Tu5gSeQXRsxo56ePPQAvFiA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31 h1:0HCMIkAkVY9KMgueD8tf4bRTUanzEYvhw7KkPXIMpO0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.31/go.mod h1:fTJDMe8LOFYtqiFFFeHA+SVMAwqLhoq0kcInYoLa9Js= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38 h1:+i1DOFrW3YZ3apE45tCal9+aDKK6kNEbW6Ib7e1nFxE= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.38/go.mod h1:1/jLp0OgOaWIetycOmycW+vYTYgTZFPttJQRgsI1PoU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31 h1:auGDJ0aLZahF5SPvkJ6WcUuX7iQ7kyl2MamV7Tm8QBk= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.31/go.mod h1:3+lloe3sZuBQw1aBc5MyndvodzQlyqCZ7x1QPDHaWP4= -github.com/aws/aws-sdk-go-v2/service/lambda v1.39.1 h1:Lhk8/UeifQgYq422El43CEkICp1QHiLSKIz9W4Dygdc= -github.com/aws/aws-sdk-go-v2/service/lambda v1.39.1/go.mod h1:MiY958jauOEVweMj4Xxa81B45wTg/6ewgp3XeCLV+hg= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.1 h1:DSNpSbfEgFXRV+IfEcKE5kTbqxm+MeF5WgyeRlsLnHY= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.1/go.mod h1:TC9BubuFMVScIU+TLKamO6VZiYTkYoEHqlSQwAe2omw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1 h1:hd0SKLMdOL/Sl6Z0np1PX9LeH2gqNtBe0MhTedA8MGI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.1/go.mod h1:XO/VcyoQ8nKyKfFW/3DMsRQXsfh/052tHTWmg3xBXRg= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.1 h1:pAOJj+80tC8sPVgSDHzMYD6KLWsaLQ1kZw31PTeORbs= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.1/go.mod h1:G8SbvL0rFk4WOJroU8tKBczhsbhj2p/YY7qeJezJ3CI= -github.com/aws/smithy-go v1.14.0 h1:+X90sB94fizKjDmwb4vyl2cTTPXTE5E2G/1mjByb0io= -github.com/aws/smithy-go v1.14.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/aws-sdk-go-v2 v1.20.1 h1:rZBf5DWr7YGrnlTK4kgDQGn1ltqOg5orCYb/UhOFZkg= +github.com/aws/aws-sdk-go-v2 v1.20.1/go.mod h1:NU06lETsFm8fUC6ZjhgDpVBcGZTFQ6XM+LZWZxMI4ac= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 h1:lN6L3LrYHeZ6xCxaIYtoWCx4GMLk4nRknsh29OMSqHY= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12/go.mod h1:TDCkEAkMTXxTs0oLBGBKpBZbk3NLh8EvAfF0Q3x8/0c= +github.com/aws/aws-sdk-go-v2/config v1.18.33 h1:JKcw5SFxFW/rpM4mOPjv0VQ11E2kxW13F3exWOy7VZU= +github.com/aws/aws-sdk-go-v2/config v1.18.33/go.mod h1:hXO/l9pgY3K5oZJldamP0pbZHdPqqk+4/maa7DSD3cA= +github.com/aws/aws-sdk-go-v2/credentials v1.13.32 h1:lIH1eKPcCY1ylR4B6PkBGRWMHO3aVenOKJHWiS4/G2w= +github.com/aws/aws-sdk-go-v2/credentials v1.13.32/go.mod h1:lL8U3v/Y79YRG69WlAho0OHIKUXCyFvSXaIvfo81sls= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8 h1:DK/9C+UN/X+1+Wm8pqaDksQr2tSLzq+8X1/rI/ZxKEQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8/go.mod h1:ce7BgLQfYr5hQFdy67oX2svto3ufGtm6oBvmsHScI1Q= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 h1:c8ed/T9T2K5I+h/JzmF5tpI46+OODQ74dzmdo+QnaMg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38/go.mod h1:qggunOChCMu9ZF/UkAfhTz25+U2rLVb3ya0Ua6TTfCA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 h1:hNeAAymUY5gu11WrrmFb3CVIp9Dar9hbo44yzzcQpzA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32/go.mod h1:0ZXSqrty4FtQ7p8TEuRde/SZm9X05KT18LAUlR40Ln0= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39 h1:fc0ukRAiP1syoSGZYu+DaE+FulSYhTiJ8WpVu5jElU4= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39/go.mod h1:WLAW8PT7+JhjZfLSWe7WEJaJu0GNo0cKc2Zyo003RBs= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 h1:dGAseBFEYxth10V23b5e2mAS+tX7oVbfYHD6dnDdAsg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32/go.mod h1:4jwAWKEkCR0anWk5+1RbfSg1R5Gzld7NLiuaq5bTR/Y= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.2 h1:LMKc3k1+bvr4xUEPrw11U/fZpJDoCZut7b+QC8OuDtY= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.2/go.mod h1:gDCQ1weogYZfHYZIVppDYgGS57zQALJiDL+9yGAts58= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 h1:A2RlEMo4SJSwbNoUUgkxTAEMduAy/8wG3eB2b2lP4gY= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.2/go.mod h1:ju+nNXUunfIFamXUIZQiICjnO/TPlOmWcYhZcSy7xaE= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 h1:OJELEgyaT2kmaBGZ+myyZbTTLobfe3ox3FSh5eYK9Qs= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2/go.mod h1:ubDBBaDFs1GHijSOTi8ljppML15GLG0HxhILtbjNNYQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.2 h1:ympg1+Lnq33XLhcK/xTG4yZHPs1Oyxu+6DEWbl7qOzA= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.2/go.mod h1:FQ/DQcOfESELfJi5ED+IPPAjI5xC6nxtSolVVB773jM= +github.com/aws/smithy-go v1.14.1 h1:EFKMUmH/iHMqLiwoEDx2rRjRQpI1YCn5jTysoaDujFs= +github.com/aws/smithy-go v1.14.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= From 1455c3b58609498b207d6a63e37f016f386a13dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 22:48:33 +0100 Subject: [PATCH 58/92] chore(deps-dev): bump aws-cdk from 2.89.0 to 2.90.0 (#2932) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8f706475180..88805244fe0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,13 @@ "package-lock.json": "^1.0.0" }, "devDependencies": { - "aws-cdk": "^2.89.0" + "aws-cdk": "^2.90.0" } }, "node_modules/aws-cdk": { - "version": "2.89.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.89.0.tgz", - "integrity": "sha512-4FF/5jNd86x9iSk/xQB1KRFWkhMWd/Z7x7tOwztgZYDj6aYR/3Xru7pb2BD6s6Oli/eeQaXTG11+eY9zdrJIQA==", + "version": "2.90.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.90.0.tgz", + "integrity": "sha512-6u9pCZeDyIo03tQBdutLD723tuHBsbOQDor72FRxq1uNFWRbVCmZ8ROk2/APAjYJbl4BK2lW9SEgAb8hapaybA==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -51,9 +51,9 @@ }, "dependencies": { "aws-cdk": { - "version": "2.89.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.89.0.tgz", - "integrity": "sha512-4FF/5jNd86x9iSk/xQB1KRFWkhMWd/Z7x7tOwztgZYDj6aYR/3Xru7pb2BD6s6Oli/eeQaXTG11+eY9zdrJIQA==", + "version": "2.90.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.90.0.tgz", + "integrity": "sha512-6u9pCZeDyIo03tQBdutLD723tuHBsbOQDor72FRxq1uNFWRbVCmZ8ROk2/APAjYJbl4BK2lW9SEgAb8hapaybA==", "dev": true, "requires": { "fsevents": "2.3.2" diff --git a/package.json b/package.json index 2b7ef9dc54e..1b3e4d4d348 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.89.0" + "aws-cdk": "^2.90.0" }, "dependencies": { "package-lock.json": "^1.0.0" From 50f4420476eaa79523758fe43b82196427a007f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Aug 2023 23:41:56 +0100 Subject: [PATCH 59/92] chore(ci): changelog rebuild (#2935) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae644074b05..de2e035a85c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,40 +29,42 @@ ## Maintenance -* **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) * **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) * **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) * **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) +* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From 2fed84b30042820371709c56aabcc25309cc1053 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 9 Aug 2023 09:26:02 +0200 Subject: [PATCH 60/92] chore(ci): changelog rebuild (#2938) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de2e035a85c..1cdf66cbe21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,24 +32,24 @@ * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) * **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) -* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) @@ -60,11 +60,11 @@ * **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From b0a36585a39b305d399bfdffe65167283d4e953f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Aug 2023 08:49:26 +0100 Subject: [PATCH 61/92] chore(deps-dev): bump ruff from 0.0.282 to 0.0.283 (#2937) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena Co-authored-by: Heitor Lessa --- .../utilities/data_classes/common.py | 2 +- .../src/context_manager_access.py | 2 +- poetry.lock | 38 +++++++++---------- pyproject.toml | 2 +- ruff.toml | 1 + 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index 7eb14c38de4..7a3fc8ab404 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -30,7 +30,7 @@ def __init__(self, data: Dict[str, Any], json_deserializer: Optional[Callable] = def __getitem__(self, key: str) -> Any: return self._data[key] - def __eq__(self, other: Any) -> bool: + def __eq__(self, other: object) -> bool: if not isinstance(other, DictWrapper): return False diff --git a/examples/batch_processing/src/context_manager_access.py b/examples/batch_processing/src/context_manager_access.py index 05cf612a6ae..dea3f881a48 100644 --- a/examples/batch_processing/src/context_manager_access.py +++ b/examples/batch_processing/src/context_manager_access.py @@ -31,7 +31,7 @@ def lambda_handler(event, context: LambdaContext): processed_messages: List[Tuple] = processor.process() for message in processed_messages: - status: Literal["success"] | Literal["fail"] = message[0] + status: Literal["success", "fail"] = message[0] cause: str = message[1] # (2)! record: SQSRecord = message[2] diff --git a/poetry.lock b/poetry.lock index 4806ea5d188..bde95949ec5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2219,28 +2219,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.282" +version = "0.0.283" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.282-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:01b76309ddab16eb258dabc5e86e73e6542f59f3ea6b4ab886ecbcfc80ce062c"}, - {file = "ruff-0.0.282-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e177cbb6dc0b1dbef5e999900d798b73e33602abf9b6c62d5d2cbe101026d931"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5374b40b6d860d334d28678a53a92f0bf04b53acdf0395900361ad54ce71cd1d"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d1ccbceb44e94fe2205b63996166e98a513a19ed23ec01d7193b7494b94ba30d"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eee9c8c50bc77eb9c0811c91d9d67ff39fe4f394c2f44ada37dac6d45e50c9f1"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:826e4de98e91450a6fe699a4e4a7cf33b9a90a2c5c270dc5b202241c37359ff8"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d99758f8bbcb8f8da99acabf711ffad5e7a015247adf27211100b3586777fd56"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f30c9958ab9cb02bf0c574c629e87c19454cbbdb82750e49e3d1559a5a8f216"}, - {file = "ruff-0.0.282-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47a7a9366ab8e4ee20df9339bef172eec7b2e9e123643bf3ede005058f5b114e"}, - {file = "ruff-0.0.282-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1f05f5e6d6df6f8b1974c08f963c33f0a4d8cfa15cba12d35ca3ece8e9be5b1f"}, - {file = "ruff-0.0.282-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0710ea2cadc504b96c1d94c414a7802369d0fff2ab7c94460344bba69135cb40"}, - {file = "ruff-0.0.282-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2ca52536e1c7603fe4cbb5ad9dc141df47c3200df782f5ec559364716ea27f96"}, - {file = "ruff-0.0.282-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:aab9ed5bfba6b0a2242a7ec9a72858c802ceeaf0076fe72b2ad455639275f22c"}, - {file = "ruff-0.0.282-py3-none-win32.whl", hash = "sha256:f51bbb64f8f29e444c16d21b269ba82e25f8d536beda3df7c9fe1816297e508e"}, - {file = "ruff-0.0.282-py3-none-win_amd64.whl", hash = "sha256:bd25085c42ebaffe336ed7bda8a0ae7b6c454a5f386ec8b2299503f79bd12bdf"}, - {file = "ruff-0.0.282-py3-none-win_arm64.whl", hash = "sha256:f03fba9621533d67d7ab995847467d78b9337e3697779ef2cea6f1deaee5fbef"}, - {file = "ruff-0.0.282.tar.gz", hash = "sha256:ef677c26bae756e4c98af6d8972da83caea550bc92ffef97a6e939ca5b24ad06"}, + {file = "ruff-0.0.283-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:d59615628b43c40b8335af0fafd544b3a09e9891829461fa2eb0d67f00570df5"}, + {file = "ruff-0.0.283-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:742d3c09bb4272d92fcd0a01a203d837488060280c28a42461e166226651a12a"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03622378270a37c61bb0f430c29f41bdf0699e8791d0d7548ad5745c737723fb"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4d36f0b3beecc01b50933795da718347ee442afa14cced5a60afe20e8335d24"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d21b29dc63d8ec246207dd7115ec39814ca74ee0f0f7b261aa82fb9c1cd8dfcf"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe095f2c3e8e557f2709945d611efd476b3eb39bdec5b258b2f88cfb8b5d136d"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b773f1dc57e642f707ee0e8bd68a0bc5ec95441367166a276e5dfdf88b21e1bf"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d539c73e207a13a915bde6c52ae8b2beb0b00c3b975e9e5d808fe288ea354a72"}, + {file = "ruff-0.0.283-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e43d3ab5c0bdb7b7a045411773b18ed115f0590a30c8d267c484393c6b0486ba"}, + {file = "ruff-0.0.283-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c5d72c97daa72f8914bf1b0c0ae4dbffc999e1945c291fa2d37c02ee4fa7f398"}, + {file = "ruff-0.0.283-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c32eb49ecf190a7bec0305270c864f796b362027b39a7d49c6fb120ea75e7b52"}, + {file = "ruff-0.0.283-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b1eae6990b078883c0cae60f1df0c31d2071f20afcec285baa363b9b6f7321cf"}, + {file = "ruff-0.0.283-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ad5a3042cbae1b82c3c953be77181a0934a6b02ba476fec4f177eb9c297e19ed"}, + {file = "ruff-0.0.283-py3-none-win32.whl", hash = "sha256:bd64f9775d96f35a236980ac98ed50fb5c755b227845612a873ad4f247c0cf8d"}, + {file = "ruff-0.0.283-py3-none-win_amd64.whl", hash = "sha256:28e3545ff24ae44e13da2b8fc706dd62a374cc74e4f5c1fbc8bc071ab0cc309f"}, + {file = "ruff-0.0.283-py3-none-win_arm64.whl", hash = "sha256:28732d956171f493b45c096d27f015e34fde065414330b68d59efcd0f3f67d5d"}, + {file = "ruff-0.0.283.tar.gz", hash = "sha256:6ee6928ad7b6b2b103d3b41517ff252cb81506dacbef01bab31fcfd0de39c5bb"}, ] [[package]] @@ -2696,4 +2696,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "6a98f15c7d5cb443e2a717298243d990a81944f2646b767aedee60962b8fc953" +content-hash = "584b4e15a5ecc0982f5eb7307c0d358c2d31563dc4509f2713c305255d0b1d91" diff --git a/pyproject.toml b/pyproject.toml index ece1830e734..3d3d70c8fba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.283" +ruff = ">=0.0.272,<0.0.284" retry2 = "^0.9.5" [tool.coverage.run] diff --git a/ruff.toml b/ruff.toml index be67606bbe5..c60fbebf3c0 100644 --- a/ruff.toml +++ b/ruff.toml @@ -35,6 +35,7 @@ ignore = [ "PLW0603", #https://beta.ruff.rs/docs/rules/global-statement/ "B904", # raise-without-from-inside-except - disabled temporarily "PLC1901", # Compare-to-empty-string - disabled temporarily + "PYI024" ] # Exclude files and directories From 08a0a7b68d2844d36c33ab8156640f4ea9632d0c Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Wed, 9 Aug 2023 13:02:47 +0100 Subject: [PATCH 62/92] refactor(metrics): move from protocol to ABC; split provider tests (#2934) --- aws_lambda_powertools/metrics/base.py | 8 +- aws_lambda_powertools/metrics/functions.py | 72 +++++ aws_lambda_powertools/metrics/metrics.py | 133 +-------- .../metrics/provider/__init__.py | 5 +- .../metrics/provider/base.py | 89 +++--- .../provider/cloudwatch_emf/cloudwatch.py | 154 +++------- .../metrics/provider/cloudwatch_emf/types.py | 24 ++ .../{cloudwatch_emf => }/cold_start.py | 0 tests/functional/metrics/conftest.py | 91 ++++++ .../test_metrics_cloudwatch_emf.py} | 269 ++---------------- .../metrics/test_metrics_provider.py | 62 ++++ 11 files changed, 358 insertions(+), 549 deletions(-) create mode 100644 aws_lambda_powertools/metrics/functions.py create mode 100644 aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py rename aws_lambda_powertools/metrics/provider/{cloudwatch_emf => }/cold_start.py (100%) create mode 100644 tests/functional/metrics/conftest.py rename tests/functional/{test_metrics.py => metrics/test_metrics_cloudwatch_emf.py} (84%) create mode 100644 tests/functional/metrics/test_metrics_provider.py diff --git a/aws_lambda_powertools/metrics/base.py b/aws_lambda_powertools/metrics/base.py index b32421431cd..2c45aa1fb3e 100644 --- a/aws_lambda_powertools/metrics/base.py +++ b/aws_lambda_powertools/metrics/base.py @@ -17,12 +17,12 @@ MetricValueError, SchemaValidationError, ) -from aws_lambda_powertools.metrics.provider.cloudwatch_emf import cold_start -from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cold_start import ( - reset_cold_start_flag, # noqa: F401 # backwards compatibility -) +from aws_lambda_powertools.metrics.provider import cold_start from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit +from aws_lambda_powertools.metrics.provider.cold_start import ( + reset_cold_start_flag, # noqa: F401 # backwards compatibility +) from aws_lambda_powertools.metrics.types import MetricNameUnitResolution from aws_lambda_powertools.shared import constants from aws_lambda_powertools.shared.functions import resolve_env_var_choice diff --git a/aws_lambda_powertools/metrics/functions.py b/aws_lambda_powertools/metrics/functions.py new file mode 100644 index 00000000000..d951c0749a3 --- /dev/null +++ b/aws_lambda_powertools/metrics/functions.py @@ -0,0 +1,72 @@ +from __future__ import annotations + +from typing import List + +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import ( + MetricResolutionError, + MetricUnitError, +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit + + +def extract_cloudwatch_metric_resolution_value(metric_resolutions: List, resolution: int | MetricResolution) -> int: + """Return metric value from CloudWatch metric unit whether that's str or MetricResolution enum + + Parameters + ---------- + unit : Union[int, MetricResolution] + Metric resolution + + Returns + ------- + int + Metric resolution value must be 1 or 60 + + Raises + ------ + MetricResolutionError + When metric resolution is not supported by CloudWatch + """ + if isinstance(resolution, MetricResolution): + return resolution.value + + if isinstance(resolution, int) and resolution in metric_resolutions: + return resolution + + raise MetricResolutionError( + f"Invalid metric resolution '{resolution}', expected either option: {metric_resolutions}", # noqa: E501 + ) + + +def extract_cloudwatch_metric_unit_value(metric_units: List, metric_valid_options: List, unit: str | MetricUnit) -> str: + """Return metric value from CloudWatch metric unit whether that's str or MetricUnit enum + + Parameters + ---------- + unit : Union[str, MetricUnit] + Metric unit + + Returns + ------- + str + Metric unit value (e.g. "Seconds", "Count/Second") + + Raises + ------ + MetricUnitError + When metric unit is not supported by CloudWatch + """ + + if isinstance(unit, str): + if unit in metric_valid_options: + unit = MetricUnit[unit].value + + if unit not in metric_units: + raise MetricUnitError( + f"Invalid metric unit '{unit}', expected either option: {metric_valid_options}", + ) + + if isinstance(unit, MetricUnit): + unit = unit.value + + return unit diff --git a/aws_lambda_powertools/metrics/metrics.py b/aws_lambda_powertools/metrics/metrics.py index d65cb62720a..900e0da7dd7 100644 --- a/aws_lambda_powertools/metrics/metrics.py +++ b/aws_lambda_powertools/metrics/metrics.py @@ -1,14 +1,15 @@ # NOTE: keeps for compatibility from __future__ import annotations -from typing import Any, Callable, Dict, Optional, Union +from typing import Any, Callable, Dict, Optional from aws_lambda_powertools.metrics.base import MetricResolution, MetricUnit from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import AmazonCloudWatchEMFProvider +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.types import CloudWatchEMFOutput class Metrics: - """Metrics create an EMF object with up to 100 metrics + """Metrics create an CloudWatch EMF object with up to 100 metrics Use Metrics when you need to create multiple metrics that have dimensions in common (e.g. service_name="payment"). @@ -115,7 +116,7 @@ def serialize_metric_set( metrics: Dict | None = None, dimensions: Dict | None = None, metadata: Dict | None = None, - ) -> Dict: + ) -> CloudWatchEMFOutput: return self.provider.serialize_metric_set(metrics=metrics, dimensions=dimensions, metadata=metadata) def add_metadata(self, key: str, value: Any) -> None: @@ -138,15 +139,6 @@ def log_metrics( default_dimensions=default_dimensions, ) - def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int: - return self.provider._extract_metric_resolution_value(resolution=resolution) - - def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: - return self.provider._extract_metric_unit_value(unit=unit) - - def _add_cold_start_metric(self, context: Any) -> None: - self.provider._add_cold_start_metric(context=context) - def set_default_dimensions(self, **dimensions) -> None: self.provider.set_default_dimensions(**dimensions) """Persist dimensions across Lambda invocations @@ -208,120 +200,3 @@ def service(self, service): # we can quickly revert and duplicate code while using self.provider EphemeralMetrics = AmazonCloudWatchEMFProvider - -# noqa: ERA001 -# class EphemeralMetrics(MetricManager): -# """Non-singleton version of Metrics to not persist metrics across instances -# -# NOTE: This is useful when you want to: -# -# - Create metrics for distinct namespaces -# - Create the same metrics with different dimensions more than once -# """ -# -# # _dimensions: Dict[str, str] = {} -# _default_dimensions: Dict[str, Any] = {} -# -# def __init__( -# self, -# service: str | None = None, -# namespace: str | None = None, -# provider: AmazonCloudWatchEMFProvider | None = None, -# ): -# super().__init__(namespace=namespace, service=service) -# -# self.default_dimensions = self._default_dimensions -# # # self.dimension_set = self._dimensions -# # self.dimension_set.update(**self._default_dimensions) -# -# self.provider = provider or AmazonCloudWatchEMFProvider( -# namespace=namespace, -# service=service, -# metric_set=self.metric_set, -# metadata_set=self.metadata_set, -# dimension_set=self.dimension_set, -# default_dimensions=self._default_dimensions, -# ) -# -# def add_metric( -# self, -# name: str, -# unit: MetricUnit | str, -# value: float, -# resolution: MetricResolution | int = 60, -# ) -> None: -# return self.provider.add_metric(name=name, unit=unit, value=value, resolution=resolution) -# -# def add_dimension(self, name: str, value: str) -> None: -# return self.provider.add_dimension(name=name, value=value) -# -# def serialize_metric_set( -# self, -# metrics: Dict | None = None, -# dimensions: Dict | None = None, -# metadata: Dict | None = None, -# ) -> Dict: -# return self.provider.serialize_metric_set(metrics=metrics, dimensions=dimensions, metadata=metadata) -# -# def add_metadata(self, key: str, value: Any) -> None: -# self.provider.add_metadata(key=key, value=value) -# -# def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: -# self.provider.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) -# -# def log_metrics( -# self, -# lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, -# capture_cold_start_metric: bool = False, -# raise_on_empty_metrics: bool = False, -# default_dimensions: Dict[str, str] | None = None, -# ): -# return self.provider.log_metrics( -# lambda_handler=lambda_handler, -# capture_cold_start_metric=capture_cold_start_metric, -# raise_on_empty_metrics=raise_on_empty_metrics, -# default_dimensions=default_dimensions, -# ) -# -# def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int: -# return self.provider._extract_metric_resolution_value(resolution=resolution) -# -# def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: -# return self.provider._extract_metric_unit_value(unit=unit) -# -# def _add_cold_start_metric(self, context: Any) -> None: -# return self.provider._add_cold_start_metric(context=context) -# -# def set_default_dimensions(self, **dimensions) -> None: -# """Persist dimensions across Lambda invocations -# -# Parameters -# ---------- -# dimensions : Dict[str, Any], optional -# metric dimensions as key=value -# -# Example -# ------- -# **Sets some default dimensions that will always be present across metrics and invocations** -# -# from aws_lambda_powertools import Metrics -# -# metrics = Metrics(namespace="ServerlessAirline", service="payment") -# metrics.set_default_dimensions(environment="demo", another="one") -# -# @metrics.log_metrics() -# def lambda_handler(): -# return True -# """ -# return self.provider.set_default_dimensions(**dimensions) -# -# def clear_default_dimensions(self) -> None: -# self.default_dimensions.clear() -# -# def clear_metrics(self) -> None: -# self.provider.clear_metrics() -# # re-add default dimensions -# self.set_default_dimensions(**self.default_dimensions) -# - -# __all__ = [] diff --git a/aws_lambda_powertools/metrics/provider/__init__.py b/aws_lambda_powertools/metrics/provider/__init__.py index 814812c135b..30019199c52 100644 --- a/aws_lambda_powertools/metrics/provider/__init__.py +++ b/aws_lambda_powertools/metrics/provider/__init__.py @@ -1,6 +1,5 @@ -from aws_lambda_powertools.metrics.provider.base import MetricsBase, MetricsProviderBase +from aws_lambda_powertools.metrics.provider.base import BaseProvider __all__ = [ - "MetricsBase", - "MetricsProviderBase", + "BaseProvider", ] diff --git a/aws_lambda_powertools/metrics/provider/base.py b/aws_lambda_powertools/metrics/provider/base.py index 7617193033e..8bd2440658a 100644 --- a/aws_lambda_powertools/metrics/provider/base.py +++ b/aws_lambda_powertools/metrics/provider/base.py @@ -2,21 +2,20 @@ import functools import logging +from abc import ABC, abstractmethod from typing import Any, Callable, Dict, Optional -from typing_extensions import Protocol +from aws_lambda_powertools.metrics.provider import cold_start +from aws_lambda_powertools.utilities.typing import LambdaContext logger = logging.getLogger(__name__) -is_cold_start = True - -class MetricsProviderBase(Protocol): +class BaseProvider(ABC): """ - Class for metric provider interface. + Interface to create a metrics provider. - This class serves as an interface for creating your own metric provider. Inherit from this class - and implement the required methods to define your specific metric provider. + BaseProvider implements `log_metrics` decorator for every provider as a value add feature. Usage: 1. Inherit from this class. @@ -24,6 +23,7 @@ class MetricsProviderBase(Protocol): 3. Customize the behavior and functionality of the metric provider in your subclass. """ + @abstractmethod def add_metric(self, *args: Any, **kwargs: Any) -> Any: """ Abstract method for adding a metric. @@ -49,6 +49,7 @@ def add_metric(self, *args: Any, **kwargs: Any) -> Any: """ raise NotImplementedError + @abstractmethod def serialize_metric_set(self, *args: Any, **kwargs: Any) -> Any: """ Abstract method for serialize a metric. @@ -74,7 +75,7 @@ def serialize_metric_set(self, *args: Any, **kwargs: Any) -> Any: """ raise NotImplementedError - # flush serialized data to output, or send to API directly + @abstractmethod def flush_metrics(self, *args: Any, **kwargs) -> Any: """ Abstract method for flushing a metric. @@ -95,22 +96,12 @@ def flush_metrics(self, *args: Any, **kwargs) -> Any: """ raise NotImplementedError - -class MetricsBase(Protocol): - """ - Class for metric template. - - This class serves as a template for creating your own metric class. Inherit from this class - and implement the necessary methods to define your specific metric. - - NOTE: need to improve this docstring - """ - - def add_metric(self, *args, **kwargs): + @abstractmethod + def clear_metrics(self, *args: Any, **kwargs) -> None: """ - Abstract method for adding a metric. + Abstract method for clear metric instance. - This method must be implemented in subclasses to add a metric and return a combined metrics dictionary. + This method must be implemented in subclasses to clear the metric instance Parameters ---------- @@ -119,11 +110,6 @@ def add_metric(self, *args, **kwargs): *kwargs: Keyword arguments. - Returns - ---------- - Dict - A combined metrics dictionary. - Raises ---------- NotImplementedError @@ -131,28 +117,24 @@ def add_metric(self, *args, **kwargs): """ raise NotImplementedError - def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: - """Manually flushes the metrics. This is normally not necessary, - unless you're running on other runtimes besides Lambda, where the @log_metrics - decorator already handles things for you. - - Parameters - ---------- - raise_on_empty_metrics : bool, optional - raise exception if no metrics are emitted, by default False + @abstractmethod + def add_cold_start_metric(self, context: LambdaContext) -> Any: """ - raise NotImplementedError + Abstract method for clear metric instance. - def add_cold_start_metric(self, metric_name: str, function_name: str) -> None: - """ - Add a cold start metric for a specific function. + This method must be implemented in subclasses to add a metric and return a combined metrics dictionary. Parameters ---------- - metric_name: str - The name of the cold start metric to add. - function_name: str - The name of the function associated with the cold start metric. + *args: + Positional arguments. + *kwargs: + Keyword arguments. + + Raises + ---------- + NotImplementedError + This method must be implemented in subclasses. """ raise NotImplementedError @@ -161,6 +143,7 @@ def log_metrics( lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, capture_cold_start_metric: bool = False, raise_on_empty_metrics: bool = False, + **kwargs, ): """Decorator to serialize and publish metrics at the end of a function execution. @@ -197,6 +180,8 @@ def handler(event, context): Propagate error received """ + default_dimensions = kwargs.get("default_dimensions") + # If handler is None we've been called with parameters # Return a partial function with args filled if lambda_handler is None: @@ -205,6 +190,7 @@ def handler(event, context): self.log_metrics, capture_cold_start_metric=capture_cold_start_metric, raise_on_empty_metrics=raise_on_empty_metrics, + default_dimensions=default_dimensions, ) @functools.wraps(lambda_handler) @@ -221,24 +207,23 @@ def decorate(event, context): return decorate def _add_cold_start_metric(self, context: Any) -> None: - """Add cold start metric and function_name dimension + """ + Add cold start metric Parameters ---------- context : Any Lambda context """ - global is_cold_start - if not is_cold_start: + if not cold_start.is_cold_start: return logger.debug("Adding cold start metric and function_name dimension") - self.add_cold_start_metric(metric_name="ColdStart", function_name=context.function_name) + self.add_cold_start_metric(context=context) - is_cold_start = False + cold_start.is_cold_start = False def reset_cold_start_flag_provider(): - global is_cold_start - if not is_cold_start: - is_cold_start = True + if not cold_start.is_cold_start: + cold_start.is_cold_start = True diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py index 921fcee6045..16be60112c3 100644 --- a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py @@ -1,42 +1,42 @@ from __future__ import annotations import datetime -import functools import json import logging import numbers import os import warnings from collections import defaultdict -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any, Callable, Dict, List, Optional from aws_lambda_powertools.metrics.base import single_metric from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError -from aws_lambda_powertools.metrics.provider import MetricsProviderBase -from aws_lambda_powertools.metrics.provider.cloudwatch_emf import cold_start -from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS -from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import ( - MetricResolutionError, - MetricUnitError, +from aws_lambda_powertools.metrics.functions import ( + extract_cloudwatch_metric_resolution_value, + extract_cloudwatch_metric_unit_value, ) +from aws_lambda_powertools.metrics.provider.base import BaseProvider +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.types import CloudWatchEMFOutput from aws_lambda_powertools.metrics.types import MetricNameUnitResolution from aws_lambda_powertools.shared import constants from aws_lambda_powertools.shared.functions import resolve_env_var_choice +from aws_lambda_powertools.utilities.typing import LambdaContext logger = logging.getLogger(__name__) -class AmazonCloudWatchEMFProvider(MetricsProviderBase): - """Base class for metric functionality (namespace, metric, dimension, serialization) +class AmazonCloudWatchEMFProvider(BaseProvider): + """ + AmazonCloudWatchEMFProvider creates metrics asynchronously via CloudWatch Embedded Metric Format (EMF). - MetricManager creates metrics asynchronously thanks to CloudWatch Embedded Metric Format (EMF). CloudWatch EMF can create up to 100 metrics per EMF object - and metrics, dimensions, and namespace created via MetricManager + and metrics, dimensions, and namespace created via AmazonCloudWatchEMFProvider will adhere to the schema, will be serialized and validated against EMF Schema. - **Use `aws_lambda_powertools.metrics.metrics.Metrics` or - `aws_lambda_powertools.metrics.metric.single_metric` to create EMF metrics.** + **Use `aws_lambda_powertools.Metrics` or + `aws_lambda_powertools.single_metric` to create EMF metrics.** Environment variables --------------------- @@ -123,8 +123,15 @@ def add_metric( if not isinstance(value, numbers.Number): raise MetricValueError(f"{value} is not a valid number") - unit = self._extract_metric_unit_value(unit=unit) - resolution = self._extract_metric_resolution_value(resolution=resolution) + unit = extract_cloudwatch_metric_unit_value( + metric_units=self._metric_units, + metric_valid_options=self._metric_unit_valid_options, + unit=unit, + ) + resolution = extract_cloudwatch_metric_resolution_value( + metric_resolutions=self._metric_resolutions, + resolution=resolution, + ) metric: Dict = self.metric_set.get(name, defaultdict(list)) metric["Unit"] = unit metric["StorageResolution"] = resolution @@ -146,7 +153,7 @@ def serialize_metric_set( metrics: Dict | None = None, dimensions: Dict | None = None, metadata: Dict | None = None, - ) -> Dict: + ) -> CloudWatchEMFOutput: """Serializes metric and dimensions set Parameters @@ -232,7 +239,8 @@ def serialize_metric_set( }, ], }, - **dimensions, # "service": "test_service" + # NOTE: Mypy doesn't recognize splats '** syntax' in TypedDict + **dimensions, # type: ignore[misc] # "service": "test_service" **metadata, # "username": "test" **metric_names_and_values, # "single_metric": 1.0 } @@ -329,7 +337,7 @@ def log_metrics( lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, capture_cold_start_metric: bool = False, raise_on_empty_metrics: bool = False, - default_dimensions: Dict[str, str] | None = None, + **kwargs, ): """Decorator to serialize and publish metrics at the end of a function execution. @@ -357,8 +365,7 @@ def handler(event, context): captures cold start metric, by default False raise_on_empty_metrics : bool, optional raise exception if no metrics are emitted, by default False - default_dimensions: Dict[str, str], optional - metric dimensions as key=value that will always be present + **kwargs Raises ------ @@ -366,94 +373,19 @@ def handler(event, context): Propagate error received """ - # If handler is None we've been called with parameters - # Return a partial function with args filled - if lambda_handler is None: - logger.debug("Decorator called with parameters") - return functools.partial( - self.log_metrics, - capture_cold_start_metric=capture_cold_start_metric, - raise_on_empty_metrics=raise_on_empty_metrics, - default_dimensions=default_dimensions, - ) - - @functools.wraps(lambda_handler) - def decorate(event, context): - try: - if default_dimensions: - self.set_default_dimensions(**default_dimensions) - response = lambda_handler(event, context) - if capture_cold_start_metric: - self._add_cold_start_metric(context=context) - finally: - self.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) - - return response - - return decorate - - def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int: - """Return metric value from metric unit whether that's str or MetricResolution enum + default_dimensions = kwargs.get("default_dimensions") - Parameters - ---------- - unit : Union[int, MetricResolution] - Metric resolution - - Returns - ------- - int - Metric resolution value must be 1 or 60 + if default_dimensions: + self.set_default_dimensions(**default_dimensions) - Raises - ------ - MetricResolutionError - When metric resolution is not supported by CloudWatch - """ - if isinstance(resolution, MetricResolution): - return resolution.value - - if isinstance(resolution, int) and resolution in self._metric_resolutions: - return resolution - - raise MetricResolutionError( - f"Invalid metric resolution '{resolution}', expected either option: {self._metric_resolutions}", # noqa: E501 + return super().log_metrics( + lambda_handler=lambda_handler, + capture_cold_start_metric=capture_cold_start_metric, + raise_on_empty_metrics=raise_on_empty_metrics, + **kwargs, ) - def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: - """Return metric value from metric unit whether that's str or MetricUnit enum - - Parameters - ---------- - unit : Union[str, MetricUnit] - Metric unit - - Returns - ------- - str - Metric unit value (e.g. "Seconds", "Count/Second") - - Raises - ------ - MetricUnitError - When metric unit is not supported by CloudWatch - """ - - if isinstance(unit, str): - if unit in self._metric_unit_valid_options: - unit = MetricUnit[unit].value - - if unit not in self._metric_units: - raise MetricUnitError( - f"Invalid metric unit '{unit}', expected either option: {self._metric_unit_valid_options}", - ) - - if isinstance(unit, MetricUnit): - unit = unit.value - - return unit - - def _add_cold_start_metric(self, context: Any) -> None: + def add_cold_start_metric(self, context: LambdaContext) -> None: """Add cold start metric and function_name dimension Parameters @@ -461,13 +393,11 @@ def _add_cold_start_metric(self, context: Any) -> None: context : Any Lambda context """ - if cold_start.is_cold_start: - logger.debug("Adding cold start metric and function_name dimension") - with single_metric(name="ColdStart", unit=MetricUnit.Count, value=1, namespace=self.namespace) as metric: - metric.add_dimension(name="function_name", value=context.function_name) - if self.service: - metric.add_dimension(name="service", value=str(self.service)) - cold_start.is_cold_start = False + logger.debug("Adding cold start metric and function_name dimension") + with single_metric(name="ColdStart", unit=MetricUnit.Count, value=1, namespace=self.namespace) as metric: + metric.add_dimension(name="function_name", value=context.function_name) + if self.service: + metric.add_dimension(name="service", value=str(self.service)) def set_default_dimensions(self, **dimensions) -> None: """Persist dimensions across Lambda invocations diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py new file mode 100644 index 00000000000..bf3a48ea13f --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/cloudwatch_emf/types.py @@ -0,0 +1,24 @@ +from typing import List + +from typing_extensions import NotRequired, TypedDict + + +class CloudWatchEMFMetric(TypedDict): + Name: str + Unit: str + StorageResolution: NotRequired[int] + + +class CloudWatchEMFMetrics(TypedDict): + Namespace: str + Dimensions: List[List[str]] # [ [ 'test_dimension' ] ] + Metrics: List[CloudWatchEMFMetric] + + +class CloudWatchEMFRoot(TypedDict): + Timestamp: int + CloudWatchMetrics: List[CloudWatchEMFMetrics] + + +class CloudWatchEMFOutput(TypedDict): + _aws: CloudWatchEMFRoot diff --git a/aws_lambda_powertools/metrics/provider/cloudwatch_emf/cold_start.py b/aws_lambda_powertools/metrics/provider/cold_start.py similarity index 100% rename from aws_lambda_powertools/metrics/provider/cloudwatch_emf/cold_start.py rename to aws_lambda_powertools/metrics/provider/cold_start.py diff --git a/tests/functional/metrics/conftest.py b/tests/functional/metrics/conftest.py new file mode 100644 index 00000000000..cb0e083ca1f --- /dev/null +++ b/tests/functional/metrics/conftest.py @@ -0,0 +1,91 @@ +from typing import Any, Dict, List, Union + +import pytest + +from aws_lambda_powertools.metrics import ( + MetricResolution, + Metrics, + MetricUnit, +) +from aws_lambda_powertools.metrics.provider.cold_start import reset_cold_start_flag + + +@pytest.fixture(scope="function", autouse=True) +def reset_metric_set(): + metrics = Metrics() + metrics.clear_metrics() + metrics.clear_default_dimensions() + reset_cold_start_flag() # ensure each test has cold start + yield + + +@pytest.fixture +def metric_with_resolution() -> Dict[str, Union[str, int]]: + return {"name": "single_metric", "unit": MetricUnit.Count, "value": 1, "resolution": MetricResolution.High} + + +@pytest.fixture +def metric() -> Dict[str, str]: + return {"name": "single_metric", "unit": MetricUnit.Count, "value": 1} + + +@pytest.fixture +def metrics() -> List[Dict[str, str]]: + return [ + {"name": "metric_one", "unit": MetricUnit.Count, "value": 1}, + {"name": "metric_two", "unit": MetricUnit.Count, "value": 1}, + ] + + +@pytest.fixture +def metrics_same_name() -> List[Dict[str, str]]: + return [ + {"name": "metric_one", "unit": MetricUnit.Count, "value": 1}, + {"name": "metric_one", "unit": MetricUnit.Count, "value": 5}, + ] + + +@pytest.fixture +def dimension() -> Dict[str, str]: + return {"name": "test_dimension", "value": "test"} + + +@pytest.fixture +def dimensions() -> List[Dict[str, str]]: + return [ + {"name": "test_dimension", "value": "test"}, + {"name": "test_dimension_2", "value": "test"}, + ] + + +@pytest.fixture +def non_str_dimensions() -> List[Dict[str, Any]]: + return [ + {"name": "test_dimension", "value": True}, + {"name": "test_dimension_2", "value": 3}, + ] + + +@pytest.fixture +def namespace() -> str: + return "test_namespace" + + +@pytest.fixture +def service() -> str: + return "test_service" + + +@pytest.fixture +def metadata() -> Dict[str, str]: + return {"key": "username", "value": "test"} + + +@pytest.fixture +def a_hundred_metrics() -> List[Dict[str, str]]: + return [{"name": f"metric_{i}", "unit": "Count", "value": 1} for i in range(100)] + + +@pytest.fixture +def a_hundred_metric_values() -> List[Dict[str, str]]: + return [{"name": "metric", "unit": "Count", "value": i} for i in range(100)] diff --git a/tests/functional/test_metrics.py b/tests/functional/metrics/test_metrics_cloudwatch_emf.py similarity index 84% rename from tests/functional/test_metrics.py rename to tests/functional/metrics/test_metrics_cloudwatch_emf.py index 329ff7064dd..5c4a1de1128 100644 --- a/tests/functional/test_metrics.py +++ b/tests/functional/metrics/test_metrics_cloudwatch_emf.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import json import warnings from collections import namedtuple -from typing import Any, Dict, List, Union +from typing import Dict, List import pytest @@ -16,103 +18,23 @@ SchemaValidationError, single_metric, ) -from aws_lambda_powertools.metrics.provider import ( - MetricsBase, - MetricsProviderBase, +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import ( + AmazonCloudWatchEMFProvider, +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import ( + MAX_DIMENSIONS, +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.types import ( + CloudWatchEMFOutput, ) -from aws_lambda_powertools.metrics.provider.base import reset_cold_start_flag_provider -from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import AmazonCloudWatchEMFProvider -from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cold_start import reset_cold_start_flag -from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS - - -@pytest.fixture(scope="function", autouse=True) -def reset_metric_set(): - metrics = Metrics() - metrics.clear_metrics() - metrics.clear_default_dimensions() - reset_cold_start_flag() # ensure each test has cold start - yield - - -@pytest.fixture -def metric_with_resolution() -> Dict[str, Union[str, int]]: - return {"name": "single_metric", "unit": MetricUnit.Count, "value": 1, "resolution": MetricResolution.High} - - -@pytest.fixture -def metric() -> Dict[str, str]: - return {"name": "single_metric", "unit": MetricUnit.Count, "value": 1} - - -@pytest.fixture -def metrics() -> List[Dict[str, str]]: - return [ - {"name": "metric_one", "unit": MetricUnit.Count, "value": 1}, - {"name": "metric_two", "unit": MetricUnit.Count, "value": 1}, - ] - - -@pytest.fixture -def metrics_same_name() -> List[Dict[str, str]]: - return [ - {"name": "metric_one", "unit": MetricUnit.Count, "value": 1}, - {"name": "metric_one", "unit": MetricUnit.Count, "value": 5}, - ] - - -@pytest.fixture -def dimension() -> Dict[str, str]: - return {"name": "test_dimension", "value": "test"} - - -@pytest.fixture -def dimensions() -> List[Dict[str, str]]: - return [ - {"name": "test_dimension", "value": "test"}, - {"name": "test_dimension_2", "value": "test"}, - ] - - -@pytest.fixture -def non_str_dimensions() -> List[Dict[str, Any]]: - return [ - {"name": "test_dimension", "value": True}, - {"name": "test_dimension_2", "value": 3}, - ] - - -@pytest.fixture -def namespace() -> str: - return "test_namespace" - - -@pytest.fixture -def service() -> str: - return "test_service" - - -@pytest.fixture -def metadata() -> Dict[str, str]: - return {"key": "username", "value": "test"} - - -@pytest.fixture -def a_hundred_metrics() -> List[Dict[str, str]]: - return [{"name": f"metric_{i}", "unit": "Count", "value": 1} for i in range(100)] - - -@pytest.fixture -def a_hundred_metric_values() -> List[Dict[str, str]]: - return [{"name": "metric", "unit": "Count", "value": i} for i in range(100)] def serialize_metrics( metrics: List[Dict], dimensions: List[Dict], namespace: str, - metadatas: List[Dict] = None, -) -> Dict: + metadatas: List[Dict] | None = None, +) -> CloudWatchEMFOutput: """Helper function to build EMF object from a list of metrics, dimensions""" my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace) for dimension in dimensions: @@ -129,7 +51,12 @@ def serialize_metrics( return my_metrics.serialize_metric_set() -def serialize_single_metric(metric: Dict, dimension: Dict, namespace: str, metadata: Dict = None) -> Dict: +def serialize_single_metric( + metric: Dict, + dimension: Dict, + namespace: str, + metadata: Dict | None = None, +) -> CloudWatchEMFOutput: """Helper function to build EMF object from a given metric, dimension and namespace""" my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace) my_metrics.add_metric(**metric) @@ -151,7 +78,7 @@ def capture_metrics_output(capsys): return json.loads(capsys.readouterr().out.strip()) -def capture_metrics_output_multiple_emf_objects(capsys): +def capture_metrics_output_multiple_emf_objects(capsys) -> List[CloudWatchEMFOutput]: return [json.loads(line.strip()) for line in capsys.readouterr().out.split("\n") if line] @@ -1270,159 +1197,3 @@ def lambda_handler(evt, ctx): output = capture_metrics_output_multiple_emf_objects(capsys) assert len(output) == 2 - - -@pytest.fixture -def metrics_provider() -> MetricsProviderBase: - class MetricsProvider: - def __init__(self): - self.metric_store: List = [] - self.result: str - super().__init__() - - def add_metric(self, name: str, value: float, tag: List = None, *args, **kwargs): - self.metric_store.append({"name": name, "value": value, "tag": tag}) - - def serialize(self, raise_on_empty_metrics: bool = False, *args, **kwargs): - if raise_on_empty_metrics and len(self.metric_store) == 0: - raise SchemaValidationError("Must contain at least one metric.") - - self.result = json.dumps(self.metric_store) - - def flush(self, *args, **kwargs): - print(self.result) - - def clear(self): - self.result = "" - self.metric_store = [] - - return MetricsProvider - - -@pytest.fixture -def metrics_class() -> MetricsBase: - class MetricsClass(MetricsBase): - def __init__(self, provider): - self.provider = provider - super().__init__() - - def add_metric(self, name: str, value: float, tag: List = None, *args, **kwargs): - self.provider.add_metric(name=name, value=value, tag=tag) - - def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: - self.provider.serialize(raise_on_empty_metrics=raise_on_empty_metrics) - self.provider.flush() - self.provider.clear() - - def add_cold_start_metric(self, metric_name: str, function_name: str) -> None: - self.provider.add_metric(name=metric_name, value=1, function_name=function_name) - - return MetricsClass - - -def test_metrics_provider_basic(capsys, metrics_provider, metric): - provider = metrics_provider() - provider.add_metric(**metric) - provider.serialize() - provider.flush() - output = capture_metrics_output(capsys) - assert output[0]["name"] == metric["name"] - assert output[0]["value"] == metric["value"] - - -def test_metrics_provider_class_basic(capsys, metrics_provider, metrics_class, metric): - metrics = metrics_class(provider=metrics_provider()) - metrics.add_metric(**metric) - metrics.flush_metrics() - output = capture_metrics_output(capsys) - assert output[0]["name"] == metric["name"] - assert output[0]["value"] == metric["value"] - - -def test_metrics_provider_class_decorate(metrics_class, metrics_provider): - # GIVEN Metrics is initialized - my_metrics = metrics_class(provider=metrics_provider()) - - # WHEN log_metrics is used to serialize metrics - @my_metrics.log_metrics - def lambda_handler(evt, context): - return True - - # THEN log_metrics should invoke the function it decorates - # and return no error if we have a namespace and dimension - assert lambda_handler({}, {}) is True - - -def test_metrics_provider_class_coldstart(capsys, metrics_provider, metrics_class): - my_metrics = metrics_class(provider=metrics_provider()) - - # WHEN log_metrics is used with capture_cold_start_metric - @my_metrics.log_metrics(capture_cold_start_metric=True) - def lambda_handler(evt, context): - pass - - LambdaContext = namedtuple("LambdaContext", "function_name") - lambda_handler({}, LambdaContext("example_fn")) - - output = capture_metrics_output(capsys) - - # THEN ColdStart metric and function_name and service dimension should be logged - assert output[0]["name"] == "ColdStart" - - -def test_metrics_provider_class_no_coldstart(capsys, metrics_provider, metrics_class): - reset_cold_start_flag_provider() - my_metrics = metrics_class(provider=metrics_provider()) - - # WHEN log_metrics is used with capture_cold_start_metric - @my_metrics.log_metrics(capture_cold_start_metric=True) - def lambda_handler(evt, context): - pass - - LambdaContext = namedtuple("LambdaContext", "function_name") - lambda_handler({}, LambdaContext("example_fn")) - _ = capture_metrics_output(capsys) - # drop first one - - lambda_handler({}, LambdaContext("example_fn")) - output = capture_metrics_output(capsys) - - # no coldstart is here - assert "ColdStart" not in json.dumps(output) - - -def test_metric_provider_raise_on_empty_metrics(metrics_provider, metrics_class): - # GIVEN Metrics is initialized - my_metrics = metrics_class(provider=metrics_provider()) - - # WHEN log_metrics is used with raise_on_empty_metrics param and has no metrics - @my_metrics.log_metrics(raise_on_empty_metrics=True) - def lambda_handler(evt, context): - pass - - # THEN the raised exception should be SchemaValidationError - # and specifically about the lack of Metrics - with pytest.raises(SchemaValidationError, match="Must contain at least one metric."): - lambda_handler({}, {}) - - -def test_log_metrics_capture_cold_start_metric_once_with_provider_and_ephemeral(capsys, namespace, service): - # GIVEN Metrics is initialized - my_metrics = Metrics(service=service, namespace=namespace) - my_isolated_metrics = EphemeralMetrics(service=service, namespace=namespace) - - # WHEN log_metrics is used with capture_cold_start_metric - @my_metrics.log_metrics(capture_cold_start_metric=True) - @my_isolated_metrics.log_metrics(capture_cold_start_metric=True) - def lambda_handler(evt, context): - pass - - LambdaContext = namedtuple("LambdaContext", "function_name") - lambda_handler({}, LambdaContext("example_fn")) - - output = capture_metrics_output(capsys) - - # THEN ColdStart metric and function_name and service dimension should be logged - assert output["ColdStart"] == [1.0] - assert output["function_name"] == "example_fn" - assert output["service"] == service diff --git a/tests/functional/metrics/test_metrics_provider.py b/tests/functional/metrics/test_metrics_provider.py new file mode 100644 index 00000000000..2ed84a23a21 --- /dev/null +++ b/tests/functional/metrics/test_metrics_provider.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +import json +from typing import Any, List + +from aws_lambda_powertools.metrics import ( + SchemaValidationError, +) +from aws_lambda_powertools.metrics.metrics import Metrics +from aws_lambda_powertools.metrics.provider import BaseProvider +from aws_lambda_powertools.utilities.typing import LambdaContext + + +def capture_metrics_output(capsys): + return json.loads(capsys.readouterr().out.strip()) + + +class FakeMetricsProvider(BaseProvider): + def __init__(self): + self.metric_store: List = [] + + def add_metric(self, name: str, value: float, tag: List = None, *args, **kwargs): + self.metric_store.append({"name": name, "value": value}) + + def serialize_metric_set(self, raise_on_empty_metrics: bool = False, *args, **kwargs): + if raise_on_empty_metrics and len(self.metric_store) == 0: + raise SchemaValidationError("Must contain at least one metric.") + + self.result = json.dumps(self.metric_store) + + def flush_metrics(self, *args, **kwargs): + print(json.dumps(self.metric_store)) + + def clear_metrics(self): + self.metric_store.clear() + + def add_cold_start_metric(self, context: LambdaContext) -> Any: + self.metric_store.append({"name": "ColdStart", "value": 1, "function_name": context.function_name}) + + +def test_metrics_class_with_custom_provider(capsys, metric): + provider = FakeMetricsProvider() + metrics = Metrics(provider=provider) + metrics.add_metric(**metric) + metrics.flush_metrics() + output = capture_metrics_output(capsys) + assert output[0]["name"] == metric["name"] + assert output[0]["value"] == metric["value"] + + +def test_metrics_provider_class_decorate(): + # GIVEN Metrics is initialized + my_metrics = Metrics() + + # WHEN log_metrics is used to serialize metrics + @my_metrics.log_metrics + def lambda_handler(evt, context): + return True + + # THEN log_metrics should invoke the function it decorates + # and return no error if we have a namespace and dimension + assert lambda_handler({}, {}) is True From 0e610268a8c06f3b284c06b3d387297f88daa942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Aug 2023 23:48:50 +0100 Subject: [PATCH 63/92] chore(deps): bump actions/dependency-review-action from 3.0.6 to 3.0.7 (#2941) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 1ffd05de307..3052aec7dbc 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -19,4 +19,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: 'Dependency Review' - uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 # v3.0.6 + uses: actions/dependency-review-action@7d90b4f05fea31dde1c4a1fb3fa787e197ea93ab # v3.0.7 From e8001283dff7d9aad3a1d1896d25e7b5b41eee59 Mon Sep 17 00:00:00 2001 From: Diego Barreiro Date: Thu, 10 Aug 2023 01:00:20 +0200 Subject: [PATCH 64/92] chore(docs): include the environment variables section in the utilities documentation (#2925) Co-authored-by: Leandro Damascena --- docs/core/logger.md | 14 ++++++++++++++ docs/core/metrics.md | 12 +++++++++++- docs/core/tracer.md | 12 ++++++++++++ docs/utilities/middleware_factory.md | 10 ++++++++++ docs/utilities/parameters.md | 11 +++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 30a43a5817c..6fc48e8898f 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -24,6 +24,8 @@ Logger requires two settings: | **Logging level** | Sets how verbose Logger should be (INFO, by default) | `LOG_LEVEL` | `level` | | **Service** | Sets **service** key that will be present across all log statements | `POWERTOOLS_SERVICE_NAME` | `service` | +There are some [other environment variables](#environment-variables) which can be set to modify Logger's settings at a global scope. + ```yaml hl_lines="12-13" title="AWS Serverless Application Model (SAM) example" --8<-- "examples/logger/sam/template.yaml" ``` @@ -341,6 +343,18 @@ You can easily change the date format using one of the following parameters: --8<-- "examples/logger/src/date_formatting_output.json" ``` +### Environment variables + +The following environment variables are available to configure Logger at a global scope: + +| Setting | Description | Environment variable | Default | +|---------------------------|------------------------------------------------------------------------------|-----------------------------------------|---------| +| **Event Logging** | Whether to log the incoming event. | `POWERTOOLS_LOGGER_LOG_EVENT` | `false` | +| **Debug Sample Rate** | Sets the debug log sampling. | `POWERTOOLS_LOGGER_SAMPLE_RATE` | `0` | +| **Disable Deduplication** | Disables log deduplication filter protection to use Pytest Live Log feature. | `POWERTOOLS_LOG_DEDUPLICATION_DISABLED` | `false` | + +[`POWERTOOLS_LOGGER_LOG_EVENT`](#logging-incoming-event) can also be set on a per-method basis, and [`POWERTOOLS_LOGGER_SAMPLE_RATE`](#sampling-debug-logs) on a per-instance basis. These parameter values will override the environment variable value. + ## Advanced ### Built-in Correlation ID expressions diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 63ee307e789..2fd4cfc98d1 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -193,6 +193,16 @@ This has the advantage of keeping cold start metric separate from your applicati ???+ info We do not emit 0 as a value for ColdStart metric for cost reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank"} if you'd prefer a flag to override it. +### Environment variables + +The following environment variable is available to configure Metrics at a global scope: + +| Setting | Description | Environment variable | Default | +|--------------------|------------------------------------------------------------------------------|-----------------------------------------|---------| +| **Namespace Name** | Sets namespace used for metrics. | `POWERTOOLS_METRICS_NAMESPACE` | `None` | + +`POWERTOOLS_METRICS_NAMESPACE` is also available on a per-instance basis with the `namespace` parameter, which will consequently override the environment variable value. + ## Advanced ### Adding metadata @@ -319,7 +329,7 @@ That is why `Metrics` shares data across instances by default, as that covers 80 ## Testing your code -### Environment variables +### Setting environment variables ???+ tip Ignore this section, if: diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 413434718db..f7163564e6b 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -103,6 +103,18 @@ You can trace asynchronous functions and generator functions (including context --8<-- "examples/tracer/src/capture_method_generators.py" ``` +### Environment variables + +The following environment variables are available to configure Tracer at a global scope: + +| Setting | Description | Environment variable | Default | +|-----------------------|--------------------------------------------------|--------------------------------------|---------| +| **Disable Tracing** | Explicitly disables all tracing. | `POWERTOOLS_TRACE_DISABLED` | `false` | +| **Response Capture** | Captures Lambda or method return as metadata. | `POWERTOOLS_TRACER_CAPTURE_RESPONSE` | `true` | +| **Exception Capture** | Captures Lambda or method exception as metadata. | `POWERTOOLS_TRACER_CAPTURE_ERROR` | `true` | + +Both [`POWERTOOLS_TRACER_CAPTURE_RESPONSE`](#disabling-response-auto-capture) and [`POWERTOOLS_TRACER_CAPTURE_ERROR`](#disabling-exception-auto-capture) can be set on a per-method basis, consequently overriding the environment variable value. + ## Advanced ### Patching modules diff --git a/docs/utilities/middleware_factory.md b/docs/utilities/middleware_factory.md index 6b0847ddb47..35e5453af65 100644 --- a/docs/utilities/middleware_factory.md +++ b/docs/utilities/middleware_factory.md @@ -68,6 +68,16 @@ You can also have your own keyword arguments after the mandatory arguments. --8<-- "examples/middleware_factory/src/getting_started_middleware_with_params_payload.json" ``` +### Environment variables + +The following environment variable is available to configure the middleware factory at a global scope: + +| Setting | Description | Environment variable | Default | +|----------------------|------------------------------------------------------------------------------|-----------------------------------------|---------| +| **Middleware Trace** | Creates sub-segment for each custom middleware. | `POWERTOOLS_TRACE_MIDDLEWARES` | `false` | + +You can also use [`POWERTOOLS_TRACE_MIDDLEWARES`](#tracing-middleware-execution) on a per-method basis, which will consequently override the environment variable value. + ## Advanced For advanced use cases, you can instantiate [Tracer](../core/tracer.md){target="_blank"} inside your middleware, and add annotations as well as metadata for additional operational insights. diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index fa3241f43a8..d2d80230c77 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -107,6 +107,17 @@ The following will retrieve the latest version and store it in the cache. --8<-- "examples/parameters/src/getting_started_appconfig.py" ``` +### Environment variables + +The following environment variables are available to configure the parameter utility at a global scope: + +| Setting | Description | Environment variable | Default | +|-----------------------|--------------------------------------------------------------------------------|-------------------------------------|---------| +| **Max Age** | Adjusts for how long values are kept in cache (in seconds). | `POWERTOOLS_PARAMETERS_MAX_AGE` | `5` | +| **Debug Sample Rate** | Sets whether to decrypt or not values retrieved from AWS SSM Parameters Store. | `POWERTOOLS_PARAMETERS_SSM_DECRYPT` | `false` | + +You can also use [`POWERTOOLS_PARAMETERS_MAX_AGE`](#adjusting-cache-ttl) through the `max_age` parameter and [`POWERTOOLS_PARAMETERS_SSM_DECRYPT`](#ssmprovider) through the `decrypt` parameter to override the environment variable values. + ## Advanced ### Adjusting cache TTL From 87c34561b8d1a2fdfbdb48b0472c85aa607bf526 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:06:19 +0100 Subject: [PATCH 65/92] chore(ci): changelog rebuild (#2942) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cdf66cbe21..ecaec447097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ## Code Refactoring * **e2e:** support fail fast in get_lambda_response ([#2912](https://github.com/aws-powertools/powertools-lambda-python/issues/2912)) +* **metrics:** move from protocol to ABC; split provider tests ([#2934](https://github.com/aws-powertools/powertools-lambda-python/issues/2934)) ## Documentation @@ -29,43 +30,46 @@ ## Maintenance -* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) +* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) +* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) -* **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) -* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) -* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) +* **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) +* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) +* **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From 47ff09af721d0b2f457f220312494b19852cd64e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:12:26 +0100 Subject: [PATCH 66/92] chore(deps-dev): bump ruff from 0.0.283 to 0.0.284 (#2940) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .../src/assert_graphql_response.py | 2 + .../src/getting_all_enabled_features.py | 2 + .../get_parameter_by_name_error_handling.py | 2 + .../src/getting_started_parameter_by_name.py | 2 + poetry.lock | 38 +++++++++---------- pyproject.toml | 2 +- ruff.toml | 3 +- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/examples/event_handler_graphql/src/assert_graphql_response.py b/examples/event_handler_graphql/src/assert_graphql_response.py index 548aece15e0..d78698e109b 100644 --- a/examples/event_handler_graphql/src/assert_graphql_response.py +++ b/examples/event_handler_graphql/src/assert_graphql_response.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json from dataclasses import dataclass from pathlib import Path diff --git a/examples/feature_flags/src/getting_all_enabled_features.py b/examples/feature_flags/src/getting_all_enabled_features.py index 49877512578..088176687a9 100644 --- a/examples/feature_flags/src/getting_all_enabled_features.py +++ b/examples/feature_flags/src/getting_all_enabled_features.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from aws_lambda_powertools.event_handler import APIGatewayRestResolver from aws_lambda_powertools.utilities.feature_flags import AppConfigStore, FeatureFlags from aws_lambda_powertools.utilities.typing import LambdaContext diff --git a/examples/parameters/src/get_parameter_by_name_error_handling.py b/examples/parameters/src/get_parameter_by_name_error_handling.py index 7cae4525e83..a150beaae22 100644 --- a/examples/parameters/src/get_parameter_by_name_error_handling.py +++ b/examples/parameters/src/get_parameter_by_name_error_handling.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any from aws_lambda_powertools.utilities.parameters.ssm import get_parameters_by_name diff --git a/examples/parameters/src/getting_started_parameter_by_name.py b/examples/parameters/src/getting_started_parameter_by_name.py index 95d63937ab7..a7f6e2107a2 100644 --- a/examples/parameters/src/getting_started_parameter_by_name.py +++ b/examples/parameters/src/getting_started_parameter_by_name.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any from aws_lambda_powertools.utilities.parameters.ssm import get_parameters_by_name diff --git a/poetry.lock b/poetry.lock index bde95949ec5..70b37d851bb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2219,28 +2219,28 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.0.283" +version = "0.0.284" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.283-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:d59615628b43c40b8335af0fafd544b3a09e9891829461fa2eb0d67f00570df5"}, - {file = "ruff-0.0.283-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:742d3c09bb4272d92fcd0a01a203d837488060280c28a42461e166226651a12a"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03622378270a37c61bb0f430c29f41bdf0699e8791d0d7548ad5745c737723fb"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4d36f0b3beecc01b50933795da718347ee442afa14cced5a60afe20e8335d24"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d21b29dc63d8ec246207dd7115ec39814ca74ee0f0f7b261aa82fb9c1cd8dfcf"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe095f2c3e8e557f2709945d611efd476b3eb39bdec5b258b2f88cfb8b5d136d"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b773f1dc57e642f707ee0e8bd68a0bc5ec95441367166a276e5dfdf88b21e1bf"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d539c73e207a13a915bde6c52ae8b2beb0b00c3b975e9e5d808fe288ea354a72"}, - {file = "ruff-0.0.283-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e43d3ab5c0bdb7b7a045411773b18ed115f0590a30c8d267c484393c6b0486ba"}, - {file = "ruff-0.0.283-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c5d72c97daa72f8914bf1b0c0ae4dbffc999e1945c291fa2d37c02ee4fa7f398"}, - {file = "ruff-0.0.283-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:c32eb49ecf190a7bec0305270c864f796b362027b39a7d49c6fb120ea75e7b52"}, - {file = "ruff-0.0.283-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b1eae6990b078883c0cae60f1df0c31d2071f20afcec285baa363b9b6f7321cf"}, - {file = "ruff-0.0.283-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ad5a3042cbae1b82c3c953be77181a0934a6b02ba476fec4f177eb9c297e19ed"}, - {file = "ruff-0.0.283-py3-none-win32.whl", hash = "sha256:bd64f9775d96f35a236980ac98ed50fb5c755b227845612a873ad4f247c0cf8d"}, - {file = "ruff-0.0.283-py3-none-win_amd64.whl", hash = "sha256:28e3545ff24ae44e13da2b8fc706dd62a374cc74e4f5c1fbc8bc071ab0cc309f"}, - {file = "ruff-0.0.283-py3-none-win_arm64.whl", hash = "sha256:28732d956171f493b45c096d27f015e34fde065414330b68d59efcd0f3f67d5d"}, - {file = "ruff-0.0.283.tar.gz", hash = "sha256:6ee6928ad7b6b2b103d3b41517ff252cb81506dacbef01bab31fcfd0de39c5bb"}, + {file = "ruff-0.0.284-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8b949084941232e2c27f8d12c78c5a6a010927d712ecff17231ee1a8371c205b"}, + {file = "ruff-0.0.284-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a3930d66b35e4dc96197422381dff2a4e965e9278b5533e71ae8474ef202fab0"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1f7096038961d8bc3b956ee69d73826843eb5b39a5fa4ee717ed473ed69c95"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bcaf85907fc905d838f46490ee15f04031927bbea44c478394b0bfdeadc27362"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3660b85a9d84162a055f1add334623ae2d8022a84dcd605d61c30a57b436c32"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0a3218458b140ea794da72b20ea09cbe13c4c1cdb7ac35e797370354628f4c05"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2fe880cff13fffd735387efbcad54ba0ff1272bceea07f86852a33ca71276f4"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1d098ea74d0ce31478765d1f8b4fbdbba2efc532397b5c5e8e5ea0c13d7e5ae"}, + {file = "ruff-0.0.284-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c79ae3308e308b94635cd57a369d1e6f146d85019da2fbc63f55da183ee29b"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f86b2b1e7033c00de45cc176cf26778650fb8804073a0495aca2f674797becbb"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e37e086f4d623c05cd45a6fe5006e77a2b37d57773aad96b7802a6b8ecf9c910"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d29dfbe314e1131aa53df213fdfea7ee874dd96ea0dd1471093d93b59498384d"}, + {file = "ruff-0.0.284-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:88295fd649d0aa1f1271441df75bf06266a199497afd239fd392abcfd75acd7e"}, + {file = "ruff-0.0.284-py3-none-win32.whl", hash = "sha256:735cd62fccc577032a367c31f6a9de7c1eb4c01fa9a2e60775067f44f3fc3091"}, + {file = "ruff-0.0.284-py3-none-win_amd64.whl", hash = "sha256:f67ed868d79fbcc61ad0fa034fe6eed2e8d438d32abce9c04b7c4c1464b2cf8e"}, + {file = "ruff-0.0.284-py3-none-win_arm64.whl", hash = "sha256:1292cfc764eeec3cde35b3a31eae3f661d86418b5e220f5d5dba1c27a6eccbb6"}, + {file = "ruff-0.0.284.tar.gz", hash = "sha256:ebd3cc55cd499d326aac17a331deaea29bea206e01c08862f9b5c6e93d77a491"}, ] [[package]] @@ -2696,4 +2696,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "584b4e15a5ecc0982f5eb7307c0d358c2d31563dc4509f2713c305255d0b1d91" +content-hash = "47c1e7d74f594a0f31f4cef267382bb214b9ee2bbb139a7cc692659a1e589cdd" diff --git a/pyproject.toml b/pyproject.toml index 3d3d70c8fba..173c435d88c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" sentry-sdk = "^1.22.2" -ruff = ">=0.0.272,<0.0.284" +ruff = ">=0.0.272,<0.0.285" retry2 = "^0.9.5" [tool.coverage.run] diff --git a/ruff.toml b/ruff.toml index c60fbebf3c0..83910e44ebf 100644 --- a/ruff.toml +++ b/ruff.toml @@ -35,7 +35,8 @@ ignore = [ "PLW0603", #https://beta.ruff.rs/docs/rules/global-statement/ "B904", # raise-without-from-inside-except - disabled temporarily "PLC1901", # Compare-to-empty-string - disabled temporarily - "PYI024" + "PYI024", + "FA100" # Enable this rule when drop support to Python 3.7 ] # Exclude files and directories From 6b3e452b443e6da616bcd2f9fd10eb301087f1b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 22:16:11 +0100 Subject: [PATCH 67/92] chore(deps): bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 (#2943) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 465ee561c4a..98012b067ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -237,12 +237,12 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@f8c70e705ffc13c3b4d1221169b84f12a75d6ca8 # v1.8.8 + uses: pypa/gh-action-pypi-publish@ade57f54dcc56d4858ca681c80269c26dc7b9149 # v1.8.9 # PyPi test maintenance affected us numerous times, leaving for history purposes # - name: Upload to PyPi test # if: ${{ !inputs.skip_pypi }} - # uses: pypa/gh-action-pypi-publish@f8c70e705ffc13c3b4d1221169b84f12a75d6ca8 # v1.8.8 + # uses: pypa/gh-action-pypi-publish@ade57f54dcc56d4858ca681c80269c26dc7b9149 # v1.8.9 # with: # repository-url: https://test.pypi.org/legacy/ From 812b95a34c0e1bec2b1e939975b798b968bfab0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Aug 2023 00:13:07 +0100 Subject: [PATCH 68/92] chore(deps-dev): bump the boto-typing group with 1 update (#2944) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 70b37d851bb..d9a31ed61f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1544,13 +1544,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-secretsmanager" -version = "1.28.16" -description = "Type annotations for boto3.SecretsManager 1.28.16 service generated with mypy-boto3-builder 7.17.1" +version = "1.28.24" +description = "Type annotations for boto3.SecretsManager 1.28.24 service generated with mypy-boto3-builder 7.17.2" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-secretsmanager-1.28.16.tar.gz", hash = "sha256:07f443b31d2114ac363cfbdbc5f4b97934ca48fb99734bbd06d5c39bce244b83"}, - {file = "mypy_boto3_secretsmanager-1.28.16-py3-none-any.whl", hash = "sha256:05508c3a96d96e482e5aff21b508319a1911e6662aea5be96aa7f7089b8dbfd4"}, + {file = "mypy-boto3-secretsmanager-1.28.24.tar.gz", hash = "sha256:13461d8d2891ec0e430437dbb71c0879ee431ddfedb6b21c265878642faeb2a7"}, + {file = "mypy_boto3_secretsmanager-1.28.24-py3-none-any.whl", hash = "sha256:e224809e28d99c1360bfe6428e8b567bb4a43c38a71263eba0ff4de7fa321142"}, ] [package.dependencies] @@ -2696,4 +2696,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "47c1e7d74f594a0f31f4cef267382bb214b9ee2bbb139a7cc692659a1e589cdd" +content-hash = "bda535adaf225acfc4e90829893a0f7677761596824fd3c8e6bea4ff24fad07a" diff --git a/pyproject.toml b/pyproject.toml index 173c435d88c..51cab19741c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ mypy-boto3-cloudwatch = "^1.28.16" mypy-boto3-dynamodb = "^1.28.19" mypy-boto3-lambda = "^1.28.19" mypy-boto3-logs = "^1.28.16" -mypy-boto3-secretsmanager = "^1.28.16" +mypy-boto3-secretsmanager = "^1.28.24" mypy-boto3-ssm = "^1.28.16" mypy-boto3-s3 = "^1.28.19" mypy-boto3-xray = "^1.28.16" From 6de632dee5240e7b74d47c4c203c46bba5218fcc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:55:07 +0200 Subject: [PATCH 69/92] chore(ci): changelog rebuild (#2945) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecaec447097..84e2c81efd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,44 +30,47 @@ ## Maintenance -* **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) +* **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) * **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) +* **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) * **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) -* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) -* **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) +* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) * **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) +* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) * **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) -* **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) -* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) -* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) * **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) +* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) +* **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) +* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From c49e59a675c0b0049454049818d6ca2b863f015b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Aug 2023 21:42:57 +0100 Subject: [PATCH 70/92] chore(deps-dev): bump aws-cdk from 2.90.0 to 2.91.0 (#2947) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88805244fe0..a293273d144 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,13 @@ "package-lock.json": "^1.0.0" }, "devDependencies": { - "aws-cdk": "^2.90.0" + "aws-cdk": "^2.91.0" } }, "node_modules/aws-cdk": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.90.0.tgz", - "integrity": "sha512-6u9pCZeDyIo03tQBdutLD723tuHBsbOQDor72FRxq1uNFWRbVCmZ8ROk2/APAjYJbl4BK2lW9SEgAb8hapaybA==", + "version": "2.91.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.91.0.tgz", + "integrity": "sha512-YSnTiLyNtng0eW1y9XdyopSTP3Kuyhs5cF5iRcaCk9o+3zrvadgxvcWVT7caXNfE8iOI9IKwSd2GiABeVd20eQ==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -51,9 +51,9 @@ }, "dependencies": { "aws-cdk": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.90.0.tgz", - "integrity": "sha512-6u9pCZeDyIo03tQBdutLD723tuHBsbOQDor72FRxq1uNFWRbVCmZ8ROk2/APAjYJbl4BK2lW9SEgAb8hapaybA==", + "version": "2.91.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.91.0.tgz", + "integrity": "sha512-YSnTiLyNtng0eW1y9XdyopSTP3Kuyhs5cF5iRcaCk9o+3zrvadgxvcWVT7caXNfE8iOI9IKwSd2GiABeVd20eQ==", "dev": true, "requires": { "fsevents": "2.3.2" diff --git a/package.json b/package.json index 1b3e4d4d348..485a25885b2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.90.0" + "aws-cdk": "^2.91.0" }, "dependencies": { "package-lock.json": "^1.0.0" From 8c4958c6cb07f051ce234aded4c5b87704f4cc7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Aug 2023 23:15:06 +0100 Subject: [PATCH 71/92] chore(deps): bump gitpython from 3.1.31 to 3.1.32 in /docs (#2948) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/requirements.txt | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 5030fc70306..42d3c2ab26e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -16,16 +16,10 @@ gitdb==4.0.10 \ --hash=sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a \ --hash=sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7 # via gitpython -gitpython==3.1.31 \ - --hash=sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573 \ - --hash=sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d +gitpython==3.1.32 \ + --hash=sha256:8d9b8cb1e80b9735e8717c9362079d3ce4c6e5ddeebedd0361b228c3a67a62f6 \ + --hash=sha256:e3d59b1c2c6ebb9dfa7a184daf3b6dd4914237e7488a1730a6d8f6f5d0b4187f # via mkdocs-git-revision-date-plugin -importlib-metadata==6.7.0 \ - --hash=sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4 \ - --hash=sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5 - # via - # markdown - # mkdocs jinja2==3.1.2 \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 @@ -192,7 +186,3 @@ watchdog==3.0.0 \ --hash=sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44 \ --hash=sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33 # via mkdocs -zipp==3.15.0 \ - --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ - --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 - # via importlib-metadata From 8d8741e7a4e2e7fe2b122a9e834462e4ea100f72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Aug 2023 23:16:35 +0100 Subject: [PATCH 72/92] chore(deps): bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 (#2946) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98012b067ef..613f3278893 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -237,12 +237,12 @@ jobs: - name: Upload to PyPi prod if: ${{ !inputs.skip_pypi }} - uses: pypa/gh-action-pypi-publish@ade57f54dcc56d4858ca681c80269c26dc7b9149 # v1.8.9 + uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e # v1.8.10 # PyPi test maintenance affected us numerous times, leaving for history purposes # - name: Upload to PyPi test # if: ${{ !inputs.skip_pypi }} - # uses: pypa/gh-action-pypi-publish@ade57f54dcc56d4858ca681c80269c26dc7b9149 # v1.8.9 + # uses: pypa/gh-action-pypi-publish@b7f401de30cb6434a1e19f805ff006643653240e # v1.8.10 # with: # repository-url: https://test.pypi.org/legacy/ From eba91525da946ffe961e48bcae9da9a1c3b4b9e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 08:34:44 +0100 Subject: [PATCH 73/92] chore(ci): changelog rebuild (#2952) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84e2c81efd8..caf81f591a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,44 +32,47 @@ * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) +* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) -* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump gitpython from 3.1.31 to 3.1.32 in /docs ([#2948](https://github.com/aws-powertools/powertools-lambda-python/issues/2948)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) -* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 ([#2946](https://github.com/aws-powertools/powertools-lambda-python/issues/2946)) * **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) -* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) * **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) * **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) +* **deps-dev:** bump aws-cdk from 2.90.0 to 2.91.0 ([#2947](https://github.com/aws-powertools/powertools-lambda-python/issues/2947)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) From 0485c8ab9f70274b74e1434de8175e389b4d3ac1 Mon Sep 17 00:00:00 2001 From: roy <34189329+royassis@users.noreply.github.com> Date: Mon, 14 Aug 2023 12:04:08 +0300 Subject: [PATCH 74/92] feat(event_handler): allow stripping route prefixes using regexes (#2521) Co-authored-by: Roy Assis Co-authored-by: Ruben Fonseca --- .../event_handler/api_gateway.py | 34 +++++++++++++------ .../event_handler/lambda_function_url.py | 4 +-- .../event_handler/vpc_lattice.py | 4 +-- docs/core/event_handler/api_gateway.md | 10 +++++- .../src/strip_route_prefix_regex.py | 21 ++++++++++++ .../event_handler/test_api_gateway.py | 33 ++++++++++++++++++ 6 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 examples/event_handler_rest/src/strip_route_prefix_regex.py diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 446b1eca856..1e6fe2a50bb 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -520,7 +520,7 @@ def __init__( cors: Optional[CORSConfig] = None, debug: Optional[bool] = None, serializer: Optional[Callable[[Dict], str]] = None, - strip_prefixes: Optional[List[str]] = None, + strip_prefixes: Optional[List[Union[str, Pattern]]] = None, ): """ Parameters @@ -534,9 +534,10 @@ def __init__( environment variable serializer : Callable, optional function to serialize `obj` to a JSON formatted `str`, by default json.dumps - strip_prefixes: List[str], optional - optional list of prefixes to be removed from the request path before doing the routing. This is often used - with api gateways with multiple custom mappings. + strip_prefixes: List[Union[str, Pattern]], optional + optional list of prefixes to be removed from the request path before doing the routing. + This is often used with api gateways with multiple custom mappings. + Each prefix can be a static string or a compiled regex pattern """ self._proxy_type = proxy_type self._dynamic_routes: List[Route] = [] @@ -713,10 +714,21 @@ def _remove_prefix(self, path: str) -> str: return path for prefix in self._strip_prefixes: - if path == prefix: - return "/" - if self._path_starts_with(path, prefix): - return path[len(prefix) :] + if isinstance(prefix, str): + if path == prefix: + return "/" + + if self._path_starts_with(path, prefix): + return path[len(prefix) :] + + if isinstance(prefix, Pattern): + path = re.sub(prefix, "", path) + + # When using regexes, we might get into a point where everything is removed + # from the string, so we check if it's empty and return /, since there's nothing + # else to strip anymore. + if not path: + return "/" return path @@ -911,7 +923,7 @@ def __init__( cors: Optional[CORSConfig] = None, debug: Optional[bool] = None, serializer: Optional[Callable[[Dict], str]] = None, - strip_prefixes: Optional[List[str]] = None, + strip_prefixes: Optional[List[Union[str, Pattern]]] = None, ): """Amazon API Gateway REST and HTTP API v1 payload resolver""" super().__init__(ProxyEventType.APIGatewayProxyEvent, cors, debug, serializer, strip_prefixes) @@ -942,7 +954,7 @@ def __init__( cors: Optional[CORSConfig] = None, debug: Optional[bool] = None, serializer: Optional[Callable[[Dict], str]] = None, - strip_prefixes: Optional[List[str]] = None, + strip_prefixes: Optional[List[Union[str, Pattern]]] = None, ): """Amazon API Gateway HTTP API v2 payload resolver""" super().__init__(ProxyEventType.APIGatewayProxyEventV2, cors, debug, serializer, strip_prefixes) @@ -956,7 +968,7 @@ def __init__( cors: Optional[CORSConfig] = None, debug: Optional[bool] = None, serializer: Optional[Callable[[Dict], str]] = None, - strip_prefixes: Optional[List[str]] = None, + strip_prefixes: Optional[List[Union[str, Pattern]]] = None, ): """Amazon Application Load Balancer (ALB) resolver""" super().__init__(ProxyEventType.ALBEvent, cors, debug, serializer, strip_prefixes) diff --git a/aws_lambda_powertools/event_handler/lambda_function_url.py b/aws_lambda_powertools/event_handler/lambda_function_url.py index 6978b29f451..433a013ab0b 100644 --- a/aws_lambda_powertools/event_handler/lambda_function_url.py +++ b/aws_lambda_powertools/event_handler/lambda_function_url.py @@ -1,4 +1,4 @@ -from typing import Callable, Dict, List, Optional +from typing import Callable, Dict, List, Optional, Pattern, Union from aws_lambda_powertools.event_handler import CORSConfig from aws_lambda_powertools.event_handler.api_gateway import ( @@ -51,6 +51,6 @@ def __init__( cors: Optional[CORSConfig] = None, debug: Optional[bool] = None, serializer: Optional[Callable[[Dict], str]] = None, - strip_prefixes: Optional[List[str]] = None, + strip_prefixes: Optional[List[Union[str, Pattern]]] = None, ): super().__init__(ProxyEventType.LambdaFunctionUrlEvent, cors, debug, serializer, strip_prefixes) diff --git a/aws_lambda_powertools/event_handler/vpc_lattice.py b/aws_lambda_powertools/event_handler/vpc_lattice.py index 1150f7224fb..b3cb042b40b 100644 --- a/aws_lambda_powertools/event_handler/vpc_lattice.py +++ b/aws_lambda_powertools/event_handler/vpc_lattice.py @@ -1,4 +1,4 @@ -from typing import Callable, Dict, List, Optional +from typing import Callable, Dict, List, Optional, Pattern, Union from aws_lambda_powertools.event_handler import CORSConfig from aws_lambda_powertools.event_handler.api_gateway import ( @@ -47,7 +47,7 @@ def __init__( cors: Optional[CORSConfig] = None, debug: Optional[bool] = None, serializer: Optional[Callable[[Dict], str]] = None, - strip_prefixes: Optional[List[str]] = None, + strip_prefixes: Optional[List[Union[str, Pattern]]] = None, ): """Amazon VPC Lattice resolver""" super().__init__(ProxyEventType.VPCLatticeEvent, cors, debug, serializer, strip_prefixes) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 708a9de6855..dcfa38f6f9a 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -272,7 +272,7 @@ When using [Custom Domain API Mappings feature](https://docs.aws.amazon.com/apig **Scenario**: You have a custom domain `api.mydomain.dev`. Then you set `/payment` API Mapping to forward any payment requests to your Payments API. -**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/aws-powertools/powertools-lambda-roadmap/issues/34){target="_blank"}. +**Challenge**: This means your `path` value for any API requests will always contain `/payment/`, leading to HTTP 404 as Event Handler is trying to match what's after `payment/`. This gets further complicated with an [arbitrary level of nesting](https://github.com/aws-powertools/powertools-lambda/issues/34){target="_blank"}. To address this API Gateway behavior, we use `strip_prefixes` parameter to account for these prefixes that are now injected into the path regardless of which type of API Gateway you're using. @@ -293,6 +293,14 @@ To address this API Gateway behavior, we use `strip_prefixes` parameter to accou For example, when using `strip_prefixes` value of `/pay`, there is no difference between a request path of `/pay` and `/pay/`; and the path argument would be defined as `/`. +For added flexibility, you can use regexes to strip a prefix. This is helpful when you have many options due to different combinations of prefixes (e.g: multiple environments, multiple versions). + +=== "strip_route_prefix_regex.py" + + ```python hl_lines="12" + --8<-- "examples/event_handler_rest/src/strip_route_prefix_regex.py" + ``` + ## Advanced ### CORS diff --git a/examples/event_handler_rest/src/strip_route_prefix_regex.py b/examples/event_handler_rest/src/strip_route_prefix_regex.py new file mode 100644 index 00000000000..4ea4b4249f4 --- /dev/null +++ b/examples/event_handler_rest/src/strip_route_prefix_regex.py @@ -0,0 +1,21 @@ +import re + +from aws_lambda_powertools.event_handler import APIGatewayRestResolver +from aws_lambda_powertools.utilities.typing import LambdaContext + +# This will support: +# /v1/dev/subscriptions/ +# /v1/stg/subscriptions/ +# /v1/qa/subscriptions/ +# /v2/dev/subscriptions/ +# ... +app = APIGatewayRestResolver(strip_prefixes=[re.compile(r"/v[1-3]+/(dev|stg|qa)")]) + + +@app.get("/subscriptions/") +def get_subscription(subscription): + return {"subscription_id": subscription} + + +def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) diff --git a/tests/functional/event_handler/test_api_gateway.py b/tests/functional/event_handler/test_api_gateway.py index 26c71e1f27d..2afd1241bed 100644 --- a/tests/functional/event_handler/test_api_gateway.py +++ b/tests/functional/event_handler/test_api_gateway.py @@ -1,5 +1,6 @@ import base64 import json +import re import zlib from copy import deepcopy from decimal import Decimal @@ -1077,6 +1078,38 @@ def foo(): assert response["statusCode"] == 200 +@pytest.mark.parametrize( + "path", + [ + pytest.param("/stg/foo", id="path matched pay prefix"), + pytest.param("/dev/foo", id="path matched pay prefix with multiple numbers"), + pytest.param("/foo", id="path does not start with any of the prefixes"), + ], +) +def test_remove_prefix_by_regex(path: str): + app = ApiGatewayResolver(strip_prefixes=[re.compile(r"/(dev|stg)")]) + + @app.get("/foo") + def foo(): + ... + + response = app({"httpMethod": "GET", "path": path}, None) + + assert response["statusCode"] == 200 + + +def test_empty_path_when_using_regexes(): + app = ApiGatewayResolver(strip_prefixes=[re.compile(r"/(dev|stg)")]) + + @app.get("/") + def foo(): + ... + + response = app({"httpMethod": "GET", "path": "/dev"}, None) + + assert response["statusCode"] == 200 + + @pytest.mark.parametrize( "prefix", [ From 8ca9017cb46afa13ac4a83ec1405f405b0919b95 Mon Sep 17 00:00:00 2001 From: Roger Zhang Date: Mon, 14 Aug 2023 10:47:48 -0700 Subject: [PATCH 75/92] feat(metrics): add Datadog observability provider (#2906) Co-authored-by: Leandro Damascena Co-authored-by: heitorlessa --- .markdownlintignore | 2 + aws_lambda_powertools/metrics/metrics.py | 2 + .../metrics/provider/base.py | 9 +- .../metrics/provider/datadog/__init__.py | 7 + .../metrics/provider/datadog/datadog.py | 391 ++++++++++++++ .../metrics/provider/datadog/metrics.py | 126 +++++ .../metrics/provider/datadog/warnings.py | 8 + aws_lambda_powertools/shared/constants.py | 2 + docs/core/metrics.md | 34 +- docs/core/metrics/datadog.md | 259 +++++++++ docs/core/metrics/index.md | 6 + docs/index.md | 2 +- .../sam/dynamodb_batch_processing.yaml | 2 +- .../sam/kinesis_batch_processing.yaml | 2 +- .../sam/sqs_batch_processing.yaml | 2 +- examples/idempotency/templates/sam.yaml | 2 +- examples/logger/sam/template.yaml | 2 +- examples/metrics/sam/template.yaml | 2 +- .../metrics/src/clear_metrics_in_tests.py | 4 +- examples/metrics_datadog/sam/template.yaml | 39 ++ .../src/add_datadog_metrics.py | 9 + .../src/add_metrics_with_tags.py | 9 + .../src/add_metrics_with_timestamp.py | 11 + .../src/assert_single_datadog_metric.py | 9 + .../src/capture_cold_start_datadog_metric.py | 9 + .../src/capture_cold_start_metric_output.json | 8 + .../src/clear_datadog_metrics_in_tests.py | 13 + .../src/flush_datadog_metrics.py | 17 + .../src/flush_metrics_to_standard_output.py | 9 + .../src/log_metrics_output.json | 9 + .../src/log_metrics_standard_output.json | 8 + .../src/raise_on_empty_datadog_metrics.py | 10 + .../metrics_datadog/src/run_tests_env_var.sh | 1 + .../metrics_datadog/src/set_default_tags.py | 10 + .../src/set_default_tags_log_metrics.py | 11 + examples/tracer/sam/template.yaml | 2 +- includes/abbreviations.md | 1 + mkdocs.yml | 9 +- poetry.lock | 507 +++++++++++++----- pyproject.toml | 2 + tests/functional/metrics/conftest.py | 5 + .../metrics/test_metrics_datadog.py | 281 ++++++++++ tests/unit/metrics/conftest.py | 6 + tests/unit/metrics/test_functions.py | 63 +++ tests/unit/metrics/test_unit_datadog.py | 69 +++ 45 files changed, 1840 insertions(+), 151 deletions(-) create mode 100644 .markdownlintignore create mode 100644 aws_lambda_powertools/metrics/provider/datadog/__init__.py create mode 100644 aws_lambda_powertools/metrics/provider/datadog/datadog.py create mode 100644 aws_lambda_powertools/metrics/provider/datadog/metrics.py create mode 100644 aws_lambda_powertools/metrics/provider/datadog/warnings.py create mode 100644 docs/core/metrics/datadog.md create mode 100644 docs/core/metrics/index.md create mode 100644 examples/metrics_datadog/sam/template.yaml create mode 100644 examples/metrics_datadog/src/add_datadog_metrics.py create mode 100644 examples/metrics_datadog/src/add_metrics_with_tags.py create mode 100644 examples/metrics_datadog/src/add_metrics_with_timestamp.py create mode 100644 examples/metrics_datadog/src/assert_single_datadog_metric.py create mode 100644 examples/metrics_datadog/src/capture_cold_start_datadog_metric.py create mode 100644 examples/metrics_datadog/src/capture_cold_start_metric_output.json create mode 100644 examples/metrics_datadog/src/clear_datadog_metrics_in_tests.py create mode 100644 examples/metrics_datadog/src/flush_datadog_metrics.py create mode 100644 examples/metrics_datadog/src/flush_metrics_to_standard_output.py create mode 100644 examples/metrics_datadog/src/log_metrics_output.json create mode 100644 examples/metrics_datadog/src/log_metrics_standard_output.json create mode 100644 examples/metrics_datadog/src/raise_on_empty_datadog_metrics.py create mode 100644 examples/metrics_datadog/src/run_tests_env_var.sh create mode 100644 examples/metrics_datadog/src/set_default_tags.py create mode 100644 examples/metrics_datadog/src/set_default_tags_log_metrics.py create mode 100644 includes/abbreviations.md create mode 100644 tests/functional/metrics/test_metrics_datadog.py create mode 100644 tests/unit/metrics/conftest.py create mode 100644 tests/unit/metrics/test_functions.py create mode 100644 tests/unit/metrics/test_unit_datadog.py diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 00000000000..11b6d7ffe29 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,2 @@ +docs/core/metrics/index.md +includes/abbreviations.md diff --git a/aws_lambda_powertools/metrics/metrics.py b/aws_lambda_powertools/metrics/metrics.py index 900e0da7dd7..cb970fcfdc0 100644 --- a/aws_lambda_powertools/metrics/metrics.py +++ b/aws_lambda_powertools/metrics/metrics.py @@ -51,6 +51,8 @@ def lambda_handler(): service name to be used as metric dimension, by default "service_undefined" namespace : str, optional Namespace for metrics + provider: AmazonCloudWatchEMFProvider, optional + Pre-configured AmazonCloudWatchEMFProvider provider Raises ------ diff --git a/aws_lambda_powertools/metrics/provider/base.py b/aws_lambda_powertools/metrics/provider/base.py index 8bd2440658a..702b4b3d2ba 100644 --- a/aws_lambda_powertools/metrics/provider/base.py +++ b/aws_lambda_powertools/metrics/provider/base.py @@ -179,8 +179,13 @@ def handler(event, context): e Propagate error received """ + extra_args = {} - default_dimensions = kwargs.get("default_dimensions") + if kwargs.get("default_dimensions"): + extra_args.update({"default_dimensions": kwargs.get("default_dimensions")}) + + if kwargs.get("default_tags"): + extra_args.update({"default_tags": kwargs.get("default_tags")}) # If handler is None we've been called with parameters # Return a partial function with args filled @@ -190,7 +195,7 @@ def handler(event, context): self.log_metrics, capture_cold_start_metric=capture_cold_start_metric, raise_on_empty_metrics=raise_on_empty_metrics, - default_dimensions=default_dimensions, + **extra_args, ) @functools.wraps(lambda_handler) diff --git a/aws_lambda_powertools/metrics/provider/datadog/__init__.py b/aws_lambda_powertools/metrics/provider/datadog/__init__.py new file mode 100644 index 00000000000..23cb35d31eb --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/datadog/__init__.py @@ -0,0 +1,7 @@ +from aws_lambda_powertools.metrics.provider.datadog.datadog import DatadogProvider +from aws_lambda_powertools.metrics.provider.datadog.metrics import DatadogMetrics + +__all__ = [ + "DatadogMetrics", + "DatadogProvider", +] diff --git a/aws_lambda_powertools/metrics/provider/datadog/datadog.py b/aws_lambda_powertools/metrics/provider/datadog/datadog.py new file mode 100644 index 00000000000..6195589cd1b --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/datadog/datadog.py @@ -0,0 +1,391 @@ +from __future__ import annotations + +import json +import logging +import numbers +import os +import re +import time +import warnings +from typing import Any, Callable, Dict, List, Optional + +from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError +from aws_lambda_powertools.metrics.provider import BaseProvider +from aws_lambda_powertools.metrics.provider.datadog.warnings import DatadogDataValidationWarning +from aws_lambda_powertools.shared import constants +from aws_lambda_powertools.shared.functions import resolve_env_var_choice +from aws_lambda_powertools.utilities.typing import LambdaContext + +METRIC_NAME_REGEX = re.compile(r"^[a-zA-Z0-9_.]+$") + +logger = logging.getLogger(__name__) + +# Check if using datadog layer +try: + from datadog_lambda.metric import lambda_metric # type: ignore +except ImportError: # pragma: no cover + lambda_metric = None # pragma: no cover + +DEFAULT_NAMESPACE = "default" + + +class DatadogProvider(BaseProvider): + """ + DatadogProvider creates metrics asynchronously via Datadog extension or exporter. + + **Use `aws_lambda_powertools.DatadogMetrics` to create and metrics to Datadog.** + + Environment variables + --------------------- + POWERTOOLS_METRICS_NAMESPACE : str + metric namespace to be set for all metrics + + Raises + ------ + MetricValueError + When metric value isn't a number + SchemaValidationError + When metric object fails EMF schema validation + """ + + def __init__( + self, + metric_set: List | None = None, + namespace: str | None = None, + flush_to_log: bool | None = None, + default_tags: Dict[str, Any] | None = None, + ): + self.metric_set = metric_set if metric_set is not None else [] + self.namespace = ( + resolve_env_var_choice(choice=namespace, env=os.getenv(constants.METRICS_NAMESPACE_ENV)) + or DEFAULT_NAMESPACE + ) + self.default_tags = default_tags or {} + self.flush_to_log = resolve_env_var_choice(choice=flush_to_log, env=os.getenv(constants.DATADOG_FLUSH_TO_LOG)) + + # adding name,value,timestamp,tags + def add_metric( + self, + name: str, + value: float, + timestamp: int | None = None, + **tags, + ) -> None: + """ + The add_metrics function that will be used by metrics class. + + Parameters + ---------- + name: str + Name/Key for the metrics + value: float + Value for the metrics + timestamp: int + Timestamp in int for the metrics, default = time.time() + tags: List[str] + In format like List["tag:value","tag2:value2"] + args: Any + extra args will be dropped for compatibility + kwargs: Any + extra kwargs will be converted into tags, e.g., add_metrics(sales=sam) -> tags=['sales:sam'] + + Examples + -------- + >>> provider = DatadogProvider() + >>> + >>> provider.add_metric( + >>> name='coffee_house.order_value', + >>> value=12.45, + >>> tags=['product:latte', 'order:online'], + >>> sales='sam' + >>> ) + """ + + # validating metric name + if not self._validate_datadog_metric_name(name): + docs = "https://docs.datadoghq.com/metrics/custom_metrics/#naming-custom-metrics" + raise SchemaValidationError( + f"Invalid metric name. Please ensure the metric {name} follows the requirements. \n" + f"See Datadog documentation here: \n {docs}", + ) + + # validating metric tag + self._validate_datadog_tags_name(tags) + + if not isinstance(value, numbers.Real): + raise MetricValueError(f"{value} is not a valid number") + + if not timestamp: + timestamp = int(time.time()) + + logger.debug({"details": "Appending metric", "metrics": name}) + self.metric_set.append({"m": name, "v": value, "e": timestamp, "t": tags}) + + def serialize_metric_set(self, metrics: List | None = None) -> List: + """Serializes metrics + + Example + ------- + **Serialize metrics into Datadog format** + + metrics = DatadogMetric() + # ...add metrics, tags, namespace + ret = metrics.serialize_metric_set() + + Returns + ------- + List + Serialized metrics following Datadog specification + + Raises + ------ + SchemaValidationError + Raised when serialization fail schema validation + """ + + if metrics is None: # pragma: no cover + metrics = self.metric_set + + if len(metrics) == 0: + raise SchemaValidationError("Must contain at least one metric.") + + output_list: List = [] + + logger.debug({"details": "Serializing metrics", "metrics": metrics}) + + for single_metric in metrics: + if self.namespace != DEFAULT_NAMESPACE: + metric_name = f"{self.namespace}.{single_metric['m']}" + else: + metric_name = single_metric["m"] + + output_list.append( + { + "m": metric_name, + "v": single_metric["v"], + "e": single_metric["e"], + "t": self._serialize_datadog_tags(metric_tags=single_metric["t"], default_tags=self.default_tags), + }, + ) + + return output_list + + # flush serialized data to output + def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: + """Manually flushes the metrics. This is normally not necessary, + unless you're running on other runtimes besides Lambda, where the @log_metrics + decorator already handles things for you. + + Parameters + ---------- + raise_on_empty_metrics : bool, optional + raise exception if no metrics are emitted, by default False + """ + if not raise_on_empty_metrics and len(self.metric_set) == 0: + warnings.warn( + "No application metrics to publish. The cold-start metric may be published if enabled. " + "If application metrics should never be empty, consider using 'raise_on_empty_metrics'", + stacklevel=2, + ) + + else: + logger.debug("Flushing existing metrics") + metrics = self.serialize_metric_set() + # submit through datadog extension + if lambda_metric and not self.flush_to_log: + # use lambda_metric function from datadog package, submit metrics to datadog + for metric_item in metrics: # pragma: no cover + lambda_metric( # pragma: no cover + metric_name=metric_item["m"], + value=metric_item["v"], + timestamp=metric_item["e"], + tags=metric_item["t"], + ) + else: + # dd module not found: flush to log, this format can be recognized via datadog log forwarder + # https://github.com/Datadog/datadog-lambda-python/blob/main/datadog_lambda/metric.py#L77 + for metric_item in metrics: + print(json.dumps(metric_item, separators=(",", ":"))) + + self.clear_metrics() + + def clear_metrics(self): + logger.debug("Clearing out existing metric set from memory") + self.metric_set.clear() + + def add_cold_start_metric(self, context: LambdaContext) -> None: + """Add cold start metric and function_name dimension + + Parameters + ---------- + context : Any + Lambda context + """ + logger.debug("Adding cold start metric and function_name tagging") + self.add_metric(name="ColdStart", value=1, function_name=context.function_name) + + def log_metrics( + self, + lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, + capture_cold_start_metric: bool = False, + raise_on_empty_metrics: bool = False, + **kwargs, + ): + """Decorator to serialize and publish metrics at the end of a function execution. + + Be aware that the log_metrics **does call* the decorated function (e.g. lambda_handler). + + Example + ------- + **Lambda function using tracer and metrics decorators** + + from aws_lambda_powertools import Tracer + from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics + + metrics = DatadogMetrics(namespace="powertools") + tracer = Tracer(service="payment") + + @tracer.capture_lambda_handler + @metrics.log_metrics + def handler(event, context): + ... + + Parameters + ---------- + lambda_handler : Callable[[Any, Any], Any], optional + lambda function handler, by default None + capture_cold_start_metric : bool, optional + captures cold start metric, by default False + raise_on_empty_metrics : bool, optional + raise exception if no metrics are emitted, by default False + **kwargs + + Raises + ------ + e + Propagate error received + """ + + default_tags = kwargs.get("default_tags") + + if default_tags: + self.set_default_tags(**default_tags) + + return super().log_metrics( + lambda_handler=lambda_handler, + capture_cold_start_metric=capture_cold_start_metric, + raise_on_empty_metrics=raise_on_empty_metrics, + **kwargs, + ) + + def set_default_tags(self, **tags) -> None: + """Persist tags across Lambda invocations + + Parameters + ---------- + tags : **kwargs + tags as key=value + + Example + ------- + **Sets some default dimensions that will always be present across metrics and invocations** + + from aws_lambda_powertools import Metrics + + metrics = Metrics(namespace="ServerlessAirline", service="payment") + metrics.set_default_tags(environment="demo", another="one") + + @metrics.log_metrics() + def lambda_handler(): + return True + """ + self._validate_datadog_tags_name(tags) + self.default_tags.update(**tags) + + @staticmethod + def _serialize_datadog_tags(metric_tags: Dict[str, Any], default_tags: Dict[str, Any]) -> List[str]: + """ + Serialize metric tags into a list of formatted strings for Datadog integration. + + This function takes a dictionary of metric-specific tags or default tags. + It parse these tags and converts them into a list of strings in the format "tag_key:tag_value". + + Parameters + ---------- + metric_tags: Dict[str, Any] + A dictionary containing metric-specific tags. + default_tags: Dict[str, Any] + A dictionary containing default tags applicable to all metrics. + + Returns: + ------- + List[str] + A list of formatted tag strings, each in the "tag_key:tag_value" format. + + Example: + >>> metric_tags = {'environment': 'production', 'service': 'web'} + >>> serialize_datadog_tags(metric_tags, None) + ['environment:production', 'service:web'] + """ + tags = metric_tags or default_tags + + return [f"{tag_key}:{tag_value}" for tag_key, tag_value in tags.items()] + + @staticmethod + def _validate_datadog_tags_name(tags: Dict): + """ + Validate a metric tag according to specific requirements. + + Metric tags must start with a letter. + Metric tags must not exceed 200 characters. Fewer than 100 is preferred from a UI perspective. + + More information here: https://docs.datadoghq.com/getting_started/tagging/#define-tags + + Parameters: + ---------- + tags: Dict + The metric tags to be validated. + """ + for tag_key, tag_value in tags.items(): + tag = f"{tag_key}:{tag_value}" + if not tag[0].isalpha() or len(tag) > 200: + docs = "https://docs.datadoghq.com/getting_started/tagging/#define-tags" + warnings.warn( + f"Invalid tag value. Please ensure the specific tag {tag} follows the requirements. \n" + f"May incur data loss for metrics. \n" + f"See Datadog documentation here: \n {docs}", + DatadogDataValidationWarning, + stacklevel=2, + ) + + @staticmethod + def _validate_datadog_metric_name(metric_name: str) -> bool: + """ + Validate a metric name according to specific requirements. + + Metric names must start with a letter. + Metric names must only contain ASCII alphanumerics, underscores, and periods. + Other characters, including spaces, are converted to underscores. + Unicode is not supported. + Metric names must not exceed 200 characters. Fewer than 100 is preferred from a UI perspective. + + More information here: https://docs.datadoghq.com/metrics/custom_metrics/#naming-custom-metrics + + Parameters: + ---------- + metric_name: str + The metric name to be validated. + + Returns: + ------- + bool + True if the metric name is valid, False otherwise. + """ + + # Check if the metric name starts with a letter + # Check if the metric name contains more than 200 characters + # Check if the resulting metric name only contains ASCII alphanumerics, underscores, and periods + if not metric_name[0].isalpha() or len(metric_name) > 200 or not METRIC_NAME_REGEX.match(metric_name): + return False + + return True diff --git a/aws_lambda_powertools/metrics/provider/datadog/metrics.py b/aws_lambda_powertools/metrics/provider/datadog/metrics.py new file mode 100644 index 00000000000..3ee4dc2f835 --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/datadog/metrics.py @@ -0,0 +1,126 @@ +# NOTE: keeps for compatibility +from __future__ import annotations + +from typing import Any, Callable, Dict, List, Optional + +from aws_lambda_powertools.metrics.provider.datadog.datadog import DatadogProvider + + +class DatadogMetrics: + """ + DatadogProvider creates metrics asynchronously via Datadog extension or exporter. + + **Use `aws_lambda_powertools.DatadogMetrics` to create and metrics to Datadog.** + + Example + ------- + **Creates a few metrics and publish at the end of a function execution** + + from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics + + metrics = DatadogMetrics(namespace="ServerlessAirline") + + @metrics.log_metrics(capture_cold_start_metric=True) + def lambda_handler(): + metrics.add_metric(name="item_sold", value=1, product="latte", order="online") + return True + + Environment variables + --------------------- + POWERTOOLS_METRICS_NAMESPACE : str + metric namespace + + Parameters + ---------- + flush_to_log : bool, optional + Used when using export instead of Lambda Extension + namespace : str, optional + Namespace for metrics + provider: DatadogProvider, optional + Pre-configured DatadogProvider provider + + Raises + ------ + MetricValueError + When metric value isn't a number + SchemaValidationError + When metric object fails Datadog schema validation + """ + + # NOTE: We use class attrs to share metrics data across instances + # this allows customers to initialize Metrics() throughout their code base (and middlewares) + # and not get caught by accident with metrics data loss, or data deduplication + # e.g., m1 and m2 add metric ProductCreated, however m1 has 'version' dimension but m2 doesn't + # Result: ProductCreated is created twice as we now have 2 different EMF blobs + _metrics: List = [] + _default_tags: Dict[str, Any] = {} + + def __init__( + self, + namespace: str | None = None, + flush_to_log: bool | None = None, + provider: DatadogProvider | None = None, + ): + self.metric_set = self._metrics + self.default_tags = self._default_tags + + if provider is None: + self.provider = DatadogProvider( + namespace=namespace, + flush_to_log=flush_to_log, + metric_set=self.metric_set, + ) + else: + self.provider = provider + + def add_metric( + self, + name: str, + value: float, + timestamp: int | None = None, + **tags: Any, + ) -> None: + self.provider.add_metric(name=name, value=value, timestamp=timestamp, **tags) + + def serialize_metric_set(self, metrics: List | None = None) -> List: + return self.provider.serialize_metric_set(metrics=metrics) + + def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None: + self.provider.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics) + + def log_metrics( + self, + lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None, + capture_cold_start_metric: bool = False, + raise_on_empty_metrics: bool = False, + default_tags: Dict[str, Any] | None = None, + ): + return self.provider.log_metrics( + lambda_handler=lambda_handler, + capture_cold_start_metric=capture_cold_start_metric, + raise_on_empty_metrics=raise_on_empty_metrics, + default_tags=default_tags, + ) + + def set_default_tags(self, **tags) -> None: + self.provider.set_default_tags(**tags) + self.default_tags.update(**tags) + + def clear_metrics(self) -> None: + self.provider.clear_metrics() + + def clear_default_tags(self) -> None: + self.provider.default_tags.clear() + self.default_tags.clear() + + # We now allow customers to bring their own instance + # of the DatadogProvider provider + # So we need to define getter/setter for namespace property + # To access this attribute on the provider instance. + @property + def namespace(self): + return self.provider.namespace + + @namespace.setter + def namespace(self, namespace): + self.provider.namespace = namespace diff --git a/aws_lambda_powertools/metrics/provider/datadog/warnings.py b/aws_lambda_powertools/metrics/provider/datadog/warnings.py new file mode 100644 index 00000000000..accf19526e7 --- /dev/null +++ b/aws_lambda_powertools/metrics/provider/datadog/warnings.py @@ -0,0 +1,8 @@ +class DatadogDataValidationWarning(Warning): + message: str + + def __init__(self, message: str): + self.message = message + + def __str__(self) -> str: + return self.message diff --git a/aws_lambda_powertools/shared/constants.py b/aws_lambda_powertools/shared/constants.py index 0cde7582976..20a7fbf47d2 100644 --- a/aws_lambda_powertools/shared/constants.py +++ b/aws_lambda_powertools/shared/constants.py @@ -10,6 +10,8 @@ METRICS_NAMESPACE_ENV: str = "POWERTOOLS_METRICS_NAMESPACE" +DATADOG_FLUSH_TO_LOG: str = "DD_FLUSH_TO_LOG" + SERVICE_NAME_ENV: str = "POWERTOOLS_SERVICE_NAME" XRAY_TRACE_ID_ENV: str = "_X_AMZN_TRACE_ID" LAMBDA_TASK_ROOT_ENV: str = "LAMBDA_TASK_ROOT" diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 2fd4cfc98d1..31b4ea99ce7 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -1,5 +1,5 @@ --- -title: Metrics +title: Amazon CloudWatch EMF Metrics description: Core utility --- @@ -16,7 +16,7 @@ These metrics can be visualized through [Amazon CloudWatch Console](https://cons ## 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 five 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`. @@ -197,9 +197,9 @@ This has the advantage of keeping cold start metric separate from your applicati The following environment variable is available to configure Metrics at a global scope: -| Setting | Description | Environment variable | Default | -|--------------------|------------------------------------------------------------------------------|-----------------------------------------|---------| -| **Namespace Name** | Sets namespace used for metrics. | `POWERTOOLS_METRICS_NAMESPACE` | `None` | +| Setting | Description | Environment variable | Default | +| ------------------ | -------------------------------- | ------------------------------ | ------- | +| **Namespace Name** | Sets namespace used for metrics. | `POWERTOOLS_METRICS_NAMESPACE` | `None` | `POWERTOOLS_METRICS_NAMESPACE` is also available on a per-instance basis with the `namespace` parameter, which will consequently override the environment variable value. @@ -261,7 +261,7 @@ By default it will skip all previously defined dimensions including default dime ### Flushing metrics manually -If you are using the AWS Lambda Web Adapter project, or a middleware with custom metric logic, you can use `flush_metrics()`. This method will serialize, print metrics available to standard output, and clear in-memory metrics data. +If you are using the [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter){target="_blank"} project, or a middleware with custom metric logic, you can use `flush_metrics()`. This method will serialize, print metrics available to standard output, and clear in-memory metrics data. ???+ warning This does not capture Cold Start metrics, and metric data validation still applies. @@ -286,9 +286,9 @@ You can use `EphemeralMetrics` class when looking to isolate multiple instances `EphemeralMetrics` has only one difference while keeping nearly the exact same set of features: -| Feature | Metrics | EphemeralMetrics | -| ----------------------------------------------------------------------------------------------------------- | ------- | ---------------- | -| **Share data across instances** (metrics, dimensions, metadata, etc.) | Yes | - | +| Feature | Metrics | EphemeralMetrics | +| --------------------------------------------------------------------- | ------- | ---------------- | +| **Share data across instances** (metrics, dimensions, metadata, etc.) | Yes | - | !!! question "Why not changing the default `Metrics` behaviour to not share data across instances?" @@ -327,6 +327,20 @@ These issues are exacerbated when you create **(A)** metric dimensions condition That is why `Metrics` shares data across instances by default, as that covers 80% of use cases and different personas using Powertools. This allows them to instantiate `Metrics` in multiple places throughout their code - be a separate file, a middleware, or an abstraction that sets default dimensions. +### Observability providers + +> An observability provider is an [AWS Lambda Partner](https://docs.aws.amazon.com/lambda/latest/dg/extensions-api-partners.html){target="_blank" rel="nofollow"} offering a platform for logging, metrics, traces, etc. + +We provide a thin-wrapper on top of the most requested observability providers. We strive to keep a similar UX as close as possible while keeping our value add features. + +!!! tip "Missing your preferred provider? Please create a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE){target="_blank"}." + +Current providers: + +| Provider | Notes | +| ------------------------------------- | -------------------------------------------------------- | +| [Datadog](./datadog){target="_blank"} | Uses Datadog SDK and Datadog Lambda Extension by default | + ## Testing your code ### Setting environment variables @@ -384,4 +398,4 @@ You can read standard output and assert whether metrics have been flushed. Here' ``` ???+ tip - For more elaborate assertions and comparisons, check out [our functional testing for Metrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/test_metrics.py){target="_blank"} + For more elaborate assertions and comparisons, check out [our functional testing for Metrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/metrics/test_metrics_cloudwatch_emf.py){target="_blank"} diff --git a/docs/core/metrics/datadog.md b/docs/core/metrics/datadog.md new file mode 100644 index 00000000000..fb5927b3a63 --- /dev/null +++ b/docs/core/metrics/datadog.md @@ -0,0 +1,259 @@ +--- +title: Datadog +description: Metrics provider +--- + + +This observability provider creates custom metrics by flushing metrics to [Datadog Lambda extension](https://docs.datadoghq.com/serverless/installation/python/?tab=datadogcli){target="_blank" rel="nofollow"}, or to standard output via [Datadog Forwarder](https://docs.datadoghq.com/logs/guide/forwarder/?tab=cloudformation){target="_blank" rel="nofollow"}. These metrics can be visualized in the [Datadog console](https://app.datadoghq.com/metric/explore){target="_blank" rel="nofollow"}. + + +```mermaid +stateDiagram-v2 + direction LR + LambdaFn: Your Lambda function + LambdaCode: DatadogMetrics + DatadogSDK: Datadog SDK + DatadogExtension: Datadog Lambda Extension + Datadog: Datadog Dashboard + LambdaExtension: Lambda Extension + + LambdaFn --> LambdaCode + LambdaCode --> DatadogSDK + DatadogSDK --> DatadogExtension + + state LambdaExtension { + DatadogExtension --> Datadog: async + } + +``` + +## Key features + +* Flush metrics to Datadog extension or standard output +* Validate against common metric definitions mistakes +* Support to add default tags + +## Terminologies + +If you're new to Datadog Metrics, there are three 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`. +* **Metric**. It's the name of the metric, for example: SuccessfulBooking or UpdatedBooking. +* **Tags**. Metrics metadata in key-value pair format. They help provide contextual information, and filter org organize metrics. + +You can read more details in the [Datadog official documentation](https://docs.datadoghq.com/metrics/custom_metrics/){target="_blank" rel="nofollow"}. + +## Getting started + +???+ tip + All examples shared in this documentation are available within the [project repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/examples){target="_blank" }. + +### Install + +> **Using Datadog Forwarder?** You can skip this step. + +We recommend using [Datadog SDK](https://docs.datadoghq.com/serverless/installation/python/){target="_blank" rel="nofollow"} and Datadog Lambda Extension with this feature for optimal results. + +For Datadog SDK, you can add `aws-lambda-powertools[datadog]` as a dependency in your preferred tool, or as a Lambda Layer in the following example: + +```yaml hl_lines="15-16 28 32" title="AWS Serverless Application Model (SAM) example" +--8<-- "examples/metrics_datadog/sam/template.yaml" +``` + +### Creating metrics + +You can create metrics using `add_metric`. + +By default, we will generate the current timestamp for you. Alternatively, you can use the `timestamp` parameter to set a custom one in epoch time. + +=== "add_datadog_metrics.py" + + ```python hl_lines="4 7 9" + --8<-- "examples/metrics_datadog/src/add_datadog_metrics.py" + ``` + +=== "add_metrics_with_timestamp.py" + + ```python hl_lines="11" + --8<-- "examples/metrics_datadog/src/add_metrics_with_timestamp.py" + ``` + +???+ warning "Warning: Do not create metrics outside the handler" + Metrics added in the global scope will only be added during cold start. Disregard if you that's the intended behavior. + +### Adding tags + +You can add any number of tags to your metrics via keyword arguments (`key=value`). They are helpful to filter, organize, and aggregate your metrics later. + +!!! info "We will emit a warning for tags [beyond the 200 chars limit](https://docs.datadoghq.com/getting_started/tagging/){target="_blank" rel="nofollow"}." + +=== "add_metrics_with_tags.py" + + ```python hl_lines="9" + --8<-- "examples/metrics_datadog/src/add_metrics_with_tags.py" + ``` + +### Adding default tags + +You can persist tags across Lambda invocations and `DatadogMetrics` instances via `set_default_tags` method, or `default_tags` parameter in the `log_metrics` decorator. + +If you'd like to remove them at some point, you can use the `clear_default_tags` method. + +???+ note "Metric tag takes precedence over default tags of the same name" + When adding tags with the same name via `add_metric` and `set_default_tags`, `add_metric` takes precedence. + +=== "set_default_tags.py" + + ```python hl_lines="5" + --8<-- "examples/metrics_datadog/src/set_default_tags.py" + ``` + +=== "set_default_tags_log_metrics.py" + + ```python hl_lines="6 9" + --8<-- "examples/metrics_datadog/src/set_default_tags_log_metrics.py" + ``` + +### Flushing metrics + +Use `log_metrics` decorator to automatically serialize and flush your metrics (SDK or Forwarder) at the end of your invocation. + +This decorator also ensures metrics are flushed in the event of an exception, including warning you in case you forgot to add metrics. + +=== "add_metrics.py" + + ```python hl_lines="7" + --8<-- "examples/metrics_datadog/src/add_metrics_with_tags.py" + ``` + +=== "log_metrics_output.json" + + ```json hl_lines="2 6 7" + --8<-- "examples/metrics_datadog/src/log_metrics_output.json" + ``` + +#### Raising SchemaValidationError on empty metrics + +Use `raise_on_empty_metrics=True` if you want to ensure at least one metric is always emitted. + +```python hl_lines="7" title="Failing fast if no metrics are added" +--8<-- "examples/metrics_datadog/src/raise_on_empty_datadog_metrics.py" +``` + +???+ tip "Suppressing warning messages on empty metrics" + If you expect your function to execute without publishing metrics every time, you can suppress the warning with **`warnings.filterwarnings("ignore", "No metrics to publish*")`**. + +### Capturing cold start metric + +You can optionally capture cold start metrics with `log_metrics` decorator via `capture_cold_start_metric` param. + +=== "capture_cold_start_metric.py" + + ```python hl_lines="7" + --8<-- "examples/metrics_datadog/src/capture_cold_start_datadog_metric.py" + ``` + +=== "capture_cold_start_metric_output.json" + + ```json hl_lines="2 6" + --8<-- "examples/metrics_datadog/src/capture_cold_start_metric_output.json" + ``` + +If it's a cold start invocation, this feature will: + +* Create a separate Datadog metric solely containing a metric named `ColdStart` +* Add `function_name` metric tag + +This has the advantage of keeping cold start metric separate from your application metrics, where you might have unrelated tags. + +???+ info + We do not emit 0 as a value for ColdStart metric for cost reasons. [Let us know](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=){target="_blank"} if you'd prefer a flag to override it. + +### Environment variables + +You can use any of the following environment variables to configure `DatadogMetrics`: + +| Setting | Description | Environment variable | Constructor parameter | +| -------------------- | -------------------------------------------------------------------------------- | ------------------------------ | --------------------- | +| **Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` | +| **Flush to log** | Use this when you want to flush metrics to be exported through Datadog Forwarder | `DD_FLUSH_TO_LOG` | `flush_to_log` | + +## Advanced + +### Flushing metrics manually + +If you are using the [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter){target="_blank"} project, or a middleware with custom metric logic, you can use `flush_metrics()`. This method will serialize, print metrics available to standard output, and clear in-memory metrics data. + +???+ warning + This does not capture Cold Start metrics, and metric data validation still applies. + +Contrary to the `log_metrics` decorator, you are now also responsible to flush metrics in the event of an exception. + +```python hl_lines="17" title="Manually flushing and clearing metrics from memory" +--8<-- "examples/metrics_datadog/src/flush_datadog_metrics.py" +``` + +### Integrating with Datadog Forwarder + +Use `flush_to_log=True` in `DatadogMetrics` to integrate with the legacy [Datadog Forwarder](https://docs.datadoghq.com/logs/guide/forwarder/?tab=cloudformation){target="_blank" rel="nofollow"}. + +This will serialize and flush metrics to standard output. + +=== "flush_metrics_to_standard_output.py" + + ```python hl_lines="4" + --8<-- "examples/metrics_datadog/src/flush_metrics_to_standard_output.py" + ``` + +=== "log_metrics_standard_output.json" + + ```json + --8<-- "examples/metrics_datadog/src/log_metrics_standard_output.json" + ``` + +## Testing your code + +### Setting environment variables + +???+ tip + Ignore this section, if: + + * You are explicitly setting namespace via `namespace` parameter + * You're not instantiating `DatadogMetrics` in the global namespace + + For example, `DatadogMetrics(namespace="ServerlessAirline")` + +Make sure to set `POWERTOOLS_METRICS_NAMESPACE` before running your tests to prevent failing on `SchemaValidation` exception. You can set it before you run tests or via pytest plugins like [dotenv](https://pypi.org/project/pytest-dotenv/){target="_blank" rel="nofollow"}. + +```bash title="Injecting dummy metric namespace before running tests" +--8<-- "examples/metrics_datadog/src/run_tests_env_var.sh" +``` + +1. **`DD_FLUSH_TO_LOG=True`** makes it easier to test by flushing final metrics to standard output. + +### Clearing metrics + +`DatadogMetrics` keep metrics in memory across multiple instances. If you need to test this behavior, you can use the following Pytest fixture to ensure metrics are reset incl. cold start: + +```python title="Clearing metrics between tests" +--8<-- "examples/metrics_datadog/src/clear_datadog_metrics_in_tests.py" +``` + +### Functional testing + +You can read standard output and assert whether metrics have been flushed. Here's an example using `pytest` with `capsys` built-in fixture: + +=== "assert_single_datadog_metric.py" + + ```python hl_lines="7" + --8<-- "examples/metrics_datadog/src/assert_single_datadog_metric.py" + ``` + +=== "add_datadog_metrics.py" + + ```python + --8<-- "examples/metrics_datadog/src/add_datadog_metrics.py" + ``` + +???+ tip + For more elaborate assertions and comparisons, check out [our functional testing for DatadogMetrics utility.](https://github.com/aws-powertools/powertools-lambda-python/blob/develop/tests/functional/metrics/test_metrics_datadog.py){target="_blank"} diff --git a/docs/core/metrics/index.md b/docs/core/metrics/index.md new file mode 100644 index 00000000000..359ce28eb33 --- /dev/null +++ b/docs/core/metrics/index.md @@ -0,0 +1,6 @@ +--- +title: Metrics +description: Core utility +--- + +--8<-- "docs/core/metrics.md" diff --git a/docs/index.md b/docs/index.md index 54a0f2c58ad..4ea82dd127c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -673,7 +673,7 @@ Compared with the [public Layer ARN](#lambda-layer) option, SAR allows you to ch ## Quick getting started ```bash title="Hello world example using SAM CLI" -sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.10 --no-tracing +sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.11 --no-tracing ``` ## Features diff --git a/examples/batch_processing/sam/dynamodb_batch_processing.yaml b/examples/batch_processing/sam/dynamodb_batch_processing.yaml index 2ed70d65a86..4e436c083e5 100644 --- a/examples/batch_processing/sam/dynamodb_batch_processing.yaml +++ b/examples/batch_processing/sam/dynamodb_batch_processing.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: python3.10 + Runtime: python3.11 Tracing: Active Environment: Variables: diff --git a/examples/batch_processing/sam/kinesis_batch_processing.yaml b/examples/batch_processing/sam/kinesis_batch_processing.yaml index 314d4f8c98f..6c80bd2f333 100644 --- a/examples/batch_processing/sam/kinesis_batch_processing.yaml +++ b/examples/batch_processing/sam/kinesis_batch_processing.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: python3.10 + Runtime: python3.11 Tracing: Active Environment: Variables: diff --git a/examples/batch_processing/sam/sqs_batch_processing.yaml b/examples/batch_processing/sam/sqs_batch_processing.yaml index 77871c3478b..2dd827107d4 100644 --- a/examples/batch_processing/sam/sqs_batch_processing.yaml +++ b/examples/batch_processing/sam/sqs_batch_processing.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: python3.10 + Runtime: python3.11 Tracing: Active Environment: Variables: diff --git a/examples/idempotency/templates/sam.yaml b/examples/idempotency/templates/sam.yaml index 8443a0914d7..7c2f65a6a4d 100644 --- a/examples/idempotency/templates/sam.yaml +++ b/examples/idempotency/templates/sam.yaml @@ -17,7 +17,7 @@ Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: python3.10 + Runtime: python3.11 Handler: app.py Policies: - Statement: diff --git a/examples/logger/sam/template.yaml b/examples/logger/sam/template.yaml index a72b96f32e2..ddaa2f16407 100644 --- a/examples/logger/sam/template.yaml +++ b/examples/logger/sam/template.yaml @@ -5,7 +5,7 @@ Description: Powertools for AWS Lambda (Python) version Globals: Function: Timeout: 5 - Runtime: python3.10 + Runtime: python3.11 Tracing: Active Environment: Variables: diff --git a/examples/metrics/sam/template.yaml b/examples/metrics/sam/template.yaml index 50a2964bc4b..ace4c71f2e1 100644 --- a/examples/metrics/sam/template.yaml +++ b/examples/metrics/sam/template.yaml @@ -5,7 +5,7 @@ Description: Powertools for AWS Lambda (Python) version Globals: Function: Timeout: 5 - Runtime: python3.10 + Runtime: python3.11 Tracing: Active Environment: Variables: diff --git a/examples/metrics/src/clear_metrics_in_tests.py b/examples/metrics/src/clear_metrics_in_tests.py index cea3879af83..a5462d3d9e1 100644 --- a/examples/metrics/src/clear_metrics_in_tests.py +++ b/examples/metrics/src/clear_metrics_in_tests.py @@ -1,7 +1,7 @@ import pytest from aws_lambda_powertools import Metrics -from aws_lambda_powertools.metrics import metrics as metrics_global +from aws_lambda_powertools.metrics.provider import cold_start @pytest.fixture(scope="function", autouse=True) @@ -9,6 +9,6 @@ def reset_metric_set(): # Clear out every metric data prior to every test metrics = Metrics() metrics.clear_metrics() - metrics_global.is_cold_start = True # ensure each test has cold start + cold_start.is_cold_start = True # ensure each test has cold start metrics.clear_default_dimensions() # remove persisted default dimensions, if any yield diff --git a/examples/metrics_datadog/sam/template.yaml b/examples/metrics_datadog/sam/template.yaml new file mode 100644 index 00000000000..39c8883c150 --- /dev/null +++ b/examples/metrics_datadog/sam/template.yaml @@ -0,0 +1,39 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: Powertools for AWS Lambda (Python) version + +Globals: + Function: + Timeout: 5 + Runtime: python3.11 + Tracing: Active + Environment: + Variables: + POWERTOOLS_METRICS_NAMESPACE: ServerlessAirline + # [Production setup] + # DATADOG_API_KEY_SECRET_ARN: "" + # [Development only] + DD_API_KEY: "" + # Configuration details: https://docs.datadoghq.com/serverless/installation/python/?tab=datadogcli + DD_SITE: datadoghq.com + + Layers: + # Find the latest Layer version in the official documentation + # https://docs.powertools.aws.dev/lambda/python/latest/#lambda-layer + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:40 + # Find the latest Layer version in the Datadog official documentation + + # Datadog SDK + # Latest versions: https://github.com/DataDog/datadog-lambda-python/releases + - !Sub arn:aws:lambda:${AWS::Region}:464622532012:layer:Datadog-Python310:78 + + # Datadog Lambda Extension + # Latest versions: https://github.com/DataDog/datadog-lambda-extension/releases + - !Sub arn:aws:lambda:${AWS::Region}:464622532012:layer:Datadog-Extension:45 + +Resources: + CaptureLambdaHandlerExample: + Type: AWS::Serverless::Function + Properties: + CodeUri: ../src + Handler: capture_lambda_handler.handler diff --git a/examples/metrics_datadog/src/add_datadog_metrics.py b/examples/metrics_datadog/src/add_datadog_metrics.py new file mode 100644 index 00000000000..6fe6774152e --- /dev/null +++ b/examples/metrics_datadog/src/add_datadog_metrics.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + + +@metrics.log_metrics # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + metrics.add_metric(name="SuccessfulBooking", value=1) diff --git a/examples/metrics_datadog/src/add_metrics_with_tags.py b/examples/metrics_datadog/src/add_metrics_with_tags.py new file mode 100644 index 00000000000..9ebb0680c13 --- /dev/null +++ b/examples/metrics_datadog/src/add_metrics_with_tags.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + + +@metrics.log_metrics # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + metrics.add_metric(name="SuccessfulBooking", value=1, tag1="powertools", tag2="python") diff --git a/examples/metrics_datadog/src/add_metrics_with_timestamp.py b/examples/metrics_datadog/src/add_metrics_with_timestamp.py new file mode 100644 index 00000000000..b2bef65e9ab --- /dev/null +++ b/examples/metrics_datadog/src/add_metrics_with_timestamp.py @@ -0,0 +1,11 @@ +import time + +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + + +@metrics.log_metrics # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + metrics.add_metric(name="SuccessfulBooking", value=1, timestamp=int(time.time())) diff --git a/examples/metrics_datadog/src/assert_single_datadog_metric.py b/examples/metrics_datadog/src/assert_single_datadog_metric.py new file mode 100644 index 00000000000..7b6ebf0909b --- /dev/null +++ b/examples/metrics_datadog/src/assert_single_datadog_metric.py @@ -0,0 +1,9 @@ +import add_datadog_metrics + + +def test_log_metrics(capsys): + add_datadog_metrics.lambda_handler({}, {}) + + log = capsys.readouterr().out.strip() # remove any extra line + + assert "SuccessfulBooking" in log # basic string assertion in JSON str diff --git a/examples/metrics_datadog/src/capture_cold_start_datadog_metric.py b/examples/metrics_datadog/src/capture_cold_start_datadog_metric.py new file mode 100644 index 00000000000..ec8c2fc1e19 --- /dev/null +++ b/examples/metrics_datadog/src/capture_cold_start_datadog_metric.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + + +@metrics.log_metrics(capture_cold_start_metric=True) +def lambda_handler(event: dict, context: LambdaContext): + return diff --git a/examples/metrics_datadog/src/capture_cold_start_metric_output.json b/examples/metrics_datadog/src/capture_cold_start_metric_output.json new file mode 100644 index 00000000000..ee7da985f66 --- /dev/null +++ b/examples/metrics_datadog/src/capture_cold_start_metric_output.json @@ -0,0 +1,8 @@ +{ + "m":"ColdStart", + "v":1, + "e":1691707488, + "t":[ + "function_name:HelloWorldFunction" + ] + } diff --git a/examples/metrics_datadog/src/clear_datadog_metrics_in_tests.py b/examples/metrics_datadog/src/clear_datadog_metrics_in_tests.py new file mode 100644 index 00000000000..e80552eba83 --- /dev/null +++ b/examples/metrics_datadog/src/clear_datadog_metrics_in_tests.py @@ -0,0 +1,13 @@ +import pytest + +from aws_lambda_powertools.metrics.provider import cold_start +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics + + +@pytest.fixture(scope="function", autouse=True) +def reset_metric_set(): + # Clear out every metric data prior to every test + metrics = DatadogMetrics() + metrics.clear_metrics() + cold_start.is_cold_start = True # ensure each test has cold start + yield diff --git a/examples/metrics_datadog/src/flush_datadog_metrics.py b/examples/metrics_datadog/src/flush_datadog_metrics.py new file mode 100644 index 00000000000..89e02fc2f3f --- /dev/null +++ b/examples/metrics_datadog/src/flush_datadog_metrics.py @@ -0,0 +1,17 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + + +def book_flight(flight_id: str, **kwargs): + # logic to book flight + ... + metrics.add_metric(name="SuccessfulBooking", value=1) + + +def lambda_handler(event: dict, context: LambdaContext): + try: + book_flight(flight_id=event.get("flight_id", "")) + finally: + metrics.flush_metrics() diff --git a/examples/metrics_datadog/src/flush_metrics_to_standard_output.py b/examples/metrics_datadog/src/flush_metrics_to_standard_output.py new file mode 100644 index 00000000000..a58fe877925 --- /dev/null +++ b/examples/metrics_datadog/src/flush_metrics_to_standard_output.py @@ -0,0 +1,9 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics(flush_to_log=True) + + +@metrics.log_metrics # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + metrics.add_metric(name="SuccessfulBooking", value=1) diff --git a/examples/metrics_datadog/src/log_metrics_output.json b/examples/metrics_datadog/src/log_metrics_output.json new file mode 100644 index 00000000000..782cea9dc4f --- /dev/null +++ b/examples/metrics_datadog/src/log_metrics_output.json @@ -0,0 +1,9 @@ +{ + "m":"SuccessfulBooking", + "v":1, + "e":1691707076, + "t":[ + "tag1:powertools", + "tag2:python" + ] +} diff --git a/examples/metrics_datadog/src/log_metrics_standard_output.json b/examples/metrics_datadog/src/log_metrics_standard_output.json new file mode 100644 index 00000000000..35fcb8a096a --- /dev/null +++ b/examples/metrics_datadog/src/log_metrics_standard_output.json @@ -0,0 +1,8 @@ +{ + "m":"SuccessfulBooking", + "v":1, + "e":1691768022, + "t":[ + + ] +} diff --git a/examples/metrics_datadog/src/raise_on_empty_datadog_metrics.py b/examples/metrics_datadog/src/raise_on_empty_datadog_metrics.py new file mode 100644 index 00000000000..2242b1dfe06 --- /dev/null +++ b/examples/metrics_datadog/src/raise_on_empty_datadog_metrics.py @@ -0,0 +1,10 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + + +@metrics.log_metrics(raise_on_empty_metrics=True) # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + # no metrics being created will now raise SchemaValidationError + return diff --git a/examples/metrics_datadog/src/run_tests_env_var.sh b/examples/metrics_datadog/src/run_tests_env_var.sh new file mode 100644 index 00000000000..5663afd3ba4 --- /dev/null +++ b/examples/metrics_datadog/src/run_tests_env_var.sh @@ -0,0 +1 @@ +POWERTOOLS_METRICS_NAMESPACE="ServerlessAirline" DD_FLUSH_TO_LOG="True" python -m pytest # (1)! diff --git a/examples/metrics_datadog/src/set_default_tags.py b/examples/metrics_datadog/src/set_default_tags.py new file mode 100644 index 00000000000..94d4335b212 --- /dev/null +++ b/examples/metrics_datadog/src/set_default_tags.py @@ -0,0 +1,10 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() +metrics.set_default_tags(tag1="powertools", tag2="python") + + +@metrics.log_metrics # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + metrics.add_metric(name="SuccessfulBooking", value=1) diff --git a/examples/metrics_datadog/src/set_default_tags_log_metrics.py b/examples/metrics_datadog/src/set_default_tags_log_metrics.py new file mode 100644 index 00000000000..c276c1d53ff --- /dev/null +++ b/examples/metrics_datadog/src/set_default_tags_log_metrics.py @@ -0,0 +1,11 @@ +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.utilities.typing import LambdaContext + +metrics = DatadogMetrics() + +default_tags = {"tag1": "powertools", "tag2": "python"} + + +@metrics.log_metrics(default_tags=default_tags) # ensures metrics are flushed upon request completion/failure +def lambda_handler(event: dict, context: LambdaContext): + metrics.add_metric(name="SuccessfulBooking", value=1) diff --git a/examples/tracer/sam/template.yaml b/examples/tracer/sam/template.yaml index 3eb6ef0acd0..d9e7d8a29da 100644 --- a/examples/tracer/sam/template.yaml +++ b/examples/tracer/sam/template.yaml @@ -5,7 +5,7 @@ Description: Powertools for AWS Lambda (Python) version Globals: Function: Timeout: 5 - Runtime: python3.10 + Runtime: python3.11 Tracing: Active Environment: Variables: diff --git a/includes/abbreviations.md b/includes/abbreviations.md new file mode 100644 index 00000000000..ed52b93fe64 --- /dev/null +++ b/includes/abbreviations.md @@ -0,0 +1 @@ +*[observability provider]: An AWS Lambda Observability Partner diff --git a/mkdocs.yml b/mkdocs.yml index 49bf5a347e5..1b9f4545239 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,7 +15,10 @@ nav: - Features: - core/tracer.md - core/logger.md - - core/metrics.md + - Metrics: + - core/metrics/index.md + - Amazon CloudWatch EMF: core/metrics.md + - Datadog: core/metrics/datadog.md - Event Handler: - core/event_handler/api_gateway.md - core/event_handler/appsync.md @@ -57,7 +60,6 @@ theme: features: - header.autohide - navigation.sections - - navigation.expand - navigation.top - navigation.instant - navigation.indexes @@ -73,6 +75,7 @@ theme: markdown_extensions: - admonition + - abbr - pymdownx.tabbed: alternate_style: true - pymdownx.highlight: @@ -82,6 +85,8 @@ markdown_extensions: base_path: "." check_paths: true restrict_base_path: false + auto_append: + - includes/abbreviations.md - meta - toc: permalink: true diff --git a/poetry.lock b/poetry.lock index d9a31ed61f7..a00522c4485 100644 --- a/poetry.lock +++ b/poetry.lock @@ -93,17 +93,17 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-alpha" -version = "2.89.0a0" +version = "2.91.0a0" description = "The CDK Construct Library for AWS::APIGatewayv2" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-alpha-2.89.0a0.tar.gz", hash = "sha256:8300431d4ef9d869066ad5dba955a6b9eca4825eb4ffcdb03d9ce34f82509d6a"}, - {file = "aws_cdk.aws_apigatewayv2_alpha-2.89.0a0-py3-none-any.whl", hash = "sha256:64a84542822bd085b03ac40e39f15c3fee1aaf649a0df34ecf0f288f7bc84c78"}, + {file = "aws-cdk.aws-apigatewayv2-alpha-2.91.0a0.tar.gz", hash = "sha256:a7b0e78862f3dd81cf13740df2ecda1c877545500872dc476f2dbf3807632a32"}, + {file = "aws_cdk.aws_apigatewayv2_alpha-2.91.0a0-py3-none-any.whl", hash = "sha256:e3d606055c2fe268d80f96052b583060a25fadcdee79d89a75f2eac4354f2e69"}, ] [package.dependencies] -aws-cdk-lib = "2.89.0" +aws-cdk-lib = "2.91.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -111,18 +111,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-authorizers-alpha" -version = "2.89.0a0" +version = "2.91.0a0" description = "Authorizers for AWS APIGateway V2" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.89.0a0.tar.gz", hash = "sha256:efa23f021efdca83f037569d41d7e96023c3750417fc976023688397f7f57715"}, - {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.89.0a0-py3-none-any.whl", hash = "sha256:7b56ea2889e8a340bfd4feb67f0798827bf58090d368763a59cd0223fe2dd916"}, + {file = "aws-cdk.aws-apigatewayv2-authorizers-alpha-2.91.0a0.tar.gz", hash = "sha256:cafd747af66f92755f188172f0e892503bc73c26f0d6d95e5f733c67b0307fa8"}, + {file = "aws_cdk.aws_apigatewayv2_authorizers_alpha-2.91.0a0-py3-none-any.whl", hash = "sha256:972393ad1c220708616322946ba3f8936cbe143a69e543762295c1ea02d69849"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.89.0.a0" -aws-cdk-lib = "2.89.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.91.0.a0" +aws-cdk-lib = "2.91.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -130,18 +130,18 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-aws-apigatewayv2-integrations-alpha" -version = "2.89.0a0" +version = "2.91.0a0" description = "Integrations for AWS APIGateway V2" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.89.0a0.tar.gz", hash = "sha256:81469d688a611d9ab10d528923692eba685cbb04a5d3401c02a4530b001a6a77"}, - {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.89.0a0-py3-none-any.whl", hash = "sha256:3367cf5fa8e4bb1939fcd60e919af00ecc6d97a1d046938af25b9c5bef26b4c1"}, + {file = "aws-cdk.aws-apigatewayv2-integrations-alpha-2.91.0a0.tar.gz", hash = "sha256:db607df2563f0b839795a41218a59e3ebc29e906dd08aed7b0b59aceba0bde02"}, + {file = "aws_cdk.aws_apigatewayv2_integrations_alpha-2.91.0a0-py3-none-any.whl", hash = "sha256:34d0f103846613a72cfae8419be2e4302863a1e8f6e81951b0a51c2f62ab80b3"}, ] [package.dependencies] -"aws-cdk.aws-apigatewayv2-alpha" = "2.89.0.a0" -aws-cdk-lib = "2.89.0" +"aws-cdk.aws-apigatewayv2-alpha" = "2.91.0.a0" +aws-cdk-lib = "2.91.0" constructs = ">=10.0.0,<11.0.0" jsii = ">=1.85.0,<2.0.0" publication = ">=0.0.3" @@ -149,13 +149,13 @@ typeguard = ">=2.13.3,<2.14.0" [[package]] name = "aws-cdk-lib" -version = "2.89.0" +version = "2.91.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.7" files = [ - {file = "aws-cdk-lib-2.89.0.tar.gz", hash = "sha256:8fbd1d4ee0ffeb67bcc845bef5a10575dbc678ad07f74cdb3cb4243afc433db7"}, - {file = "aws_cdk_lib-2.89.0-py3-none-any.whl", hash = "sha256:92eeebd77fe17b36029fae20f46eb601710485ea7c808c3d33fe1c71fee125bd"}, + {file = "aws-cdk-lib-2.91.0.tar.gz", hash = "sha256:1163926527a8b7da931cddea77a4824b929b3f775447c3b7427ecdef7701ce74"}, + {file = "aws_cdk_lib-2.91.0-py3-none-any.whl", hash = "sha256:ec2cadeb5727ea8259ad8a54ac9ff40502032cd2572c81f4594df93365da39da"}, ] [package.dependencies] @@ -183,13 +183,13 @@ requests = ">=0.14.0" [[package]] name = "aws-sam-translator" -version = "1.72.0" +version = "1.73.0" description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "aws-sam-translator-1.72.0.tar.gz", hash = "sha256:e688aac30943bfe0352147b792d8bbe7c1b5ed648747cd7ef6280875b249e2d8"}, - {file = "aws_sam_translator-1.72.0-py3-none-any.whl", hash = "sha256:69fe3914d61ae6690034c3fc1055743e5415d83c59c35ec5ec9ceb26cc65c8a1"}, + {file = "aws-sam-translator-1.73.0.tar.gz", hash = "sha256:bfa7cad3a78f002edeec5e39fd61b616cf84f34f61010c5dc2f7a76845fe7a02"}, + {file = "aws_sam_translator-1.73.0-py3-none-any.whl", hash = "sha256:c0132b065d743773fcd2573ed1ae60e0129fa46043fad76430261b098a811924"}, ] [package.dependencies] @@ -291,17 +291,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.28.16" +version = "1.28.24" description = "The AWS SDK for Python" optional = false python-versions = ">= 3.7" files = [ - {file = "boto3-1.28.16-py3-none-any.whl", hash = "sha256:d8e31f69fb919025a5961f8fbeb51fe92e2f753beb37fc1853138667a231cdaa"}, - {file = "boto3-1.28.16.tar.gz", hash = "sha256:aea48aedf3e8676e598e3202e732295064a4fcad5f2d2d2a699368b8c3ab492c"}, + {file = "boto3-1.28.24-py3-none-any.whl", hash = "sha256:0300ca6ec8bc136eb316b32cc1e30c66b85bc497f5a5fe42e095ae4280569708"}, + {file = "boto3-1.28.24.tar.gz", hash = "sha256:9d1b4713c888e53a218648ad71522bee9bec9d83f2999fff2494675af810b632"}, ] [package.dependencies] -botocore = ">=1.31.16,<1.32.0" +botocore = ">=1.31.24,<1.32.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.6.0,<0.7.0" @@ -310,13 +310,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.31.16" +version = "1.31.24" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.7" files = [ - {file = "botocore-1.31.16-py3-none-any.whl", hash = "sha256:92b240e2cb7b3afae5361651d2f48ee582f45d2dab53aef76eef7eec1d3ce582"}, - {file = "botocore-1.31.16.tar.gz", hash = "sha256:563e15979e763b93d78de58d0fc065f8615be12f41bab42f5ad9f412b6a224b3"}, + {file = "botocore-1.31.24-py3-none-any.whl", hash = "sha256:8c7ba9b09e9104e2d473214e1ffcf84b77e04cf6f5f2344942c1eed9e299f947"}, + {file = "botocore-1.31.24.tar.gz", hash = "sha256:2d8f412c67f9285219f52d5dbbb6ef0dfa9f606da29cbdd41b6d6474bcc4bbd4"}, ] [package.dependencies] @@ -327,6 +327,31 @@ urllib3 = ">=1.25.4,<1.27" [package.extras] crt = ["awscrt (==0.16.26)"] +[[package]] +name = "bytecode" +version = "0.13.0" +description = "Python module to generate and modify bytecode" +optional = false +python-versions = ">=3.6" +files = [ + {file = "bytecode-0.13.0-py3-none-any.whl", hash = "sha256:e69f92e7d27f99d5d7d76e6a824bd3d9ff857c72b59927aaf87e1a620f67fe50"}, + {file = "bytecode-0.13.0.tar.gz", hash = "sha256:6af3c2f0a31ce05dce41f7eea5cc380e33f5e8fbb7dcee3b52467a00acd52fcd"}, +] + +[[package]] +name = "bytecode" +version = "0.14.2" +description = "Python module to generate and modify bytecode" +optional = false +python-versions = ">=3.8" +files = [ + {file = "bytecode-0.14.2-py3-none-any.whl", hash = "sha256:e368a2b9bbd7c986133c951250db94fb32f774cfc49752a9db9073bcf9899762"}, + {file = "bytecode-0.14.2.tar.gz", hash = "sha256:386378d9025d68ddb144870ae74330a492717b11b8c9164c4034e88add808f0c"}, +] + +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} + [[package]] name = "cattrs" version = "23.1.2" @@ -598,6 +623,154 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] +[[package]] +name = "datadog" +version = "0.46.0" +description = "The Datadog Python library" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "datadog-0.46.0-py2.py3-none-any.whl", hash = "sha256:3d7bcda6177b43be4cdb52e16b4bdd4f9005716c0dd7cfea009e018c36bb7a3d"}, + {file = "datadog-0.46.0.tar.gz", hash = "sha256:e4fbc92a85e2b0919a226896ae45fc5e4b356c0c57f1c2659659dfbe0789c674"}, +] + +[package.dependencies] +requests = ">=2.6.0" + +[[package]] +name = "datadog-lambda" +version = "4.78.0" +description = "The Datadog AWS Lambda Library" +optional = false +python-versions = ">=3.7.0,<4" +files = [ + {file = "datadog_lambda-4.78.0-py3-none-any.whl", hash = "sha256:660bae6057f3b2033b0c035e9d542af491e40f9ce57b97b4891c491262b9148c"}, + {file = "datadog_lambda-4.78.0.tar.gz", hash = "sha256:3e57faa8f80ddd43b595355b92045fde8f9ed87efe8619133e82cebb87cbe434"}, +] + +[package.dependencies] +datadog = ">=0.41.0,<1.0.0" +ddtrace = "1.15.2" +importlib_metadata = {version = "*", markers = "python_version < \"3.8\""} +typing_extensions = {version = ">=4.0,<5.0", markers = "python_version < \"3.8\""} +urllib3 = "<2.0.0" +wrapt = ">=1.11.2,<2.0.0" + +[package.extras] +dev = ["boto3 (>=1.10.33,<2.0.0)", "flake8 (>=3.7.9,<4.0.0)", "httpretty (>=0.9.7,<0.10.0)", "nose2 (>=0.9.1,<0.10.0)", "requests (>=2.22.0,<3.0.0)"] + +[[package]] +name = "ddsketch" +version = "2.0.4" +description = "Distributed quantile sketches" +optional = false +python-versions = ">=2.7" +files = [ + {file = "ddsketch-2.0.4-py3-none-any.whl", hash = "sha256:3227a270fd686a29d3a7128f9352ccf852314410380fc11384356f1ae2a75938"}, + {file = "ddsketch-2.0.4.tar.gz", hash = "sha256:32f7314077fec8747d4faebaec2c854b5ffc399c5f552f73fa94024f48d74d64"}, +] + +[package.dependencies] +protobuf = {version = ">=3.0.0", markers = "python_version >= \"3.7\""} +six = "*" + +[[package]] +name = "ddtrace" +version = "1.15.2" +description = "Datadog APM client library" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "ddtrace-1.15.2-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:ca0411333fbdb0fafa06d412bbd76ab8d2647cc9dcb8a7833952ce4fe09eb421"}, + {file = "ddtrace-1.15.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e2603749f97a5191b32f710c8ec5248bb58f4f9a1cb337559f93c5f0f8cea33b"}, + {file = "ddtrace-1.15.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:8392087809e047f701e38ecc4f2990bcfe399a22c516a1dbcbdff50fb7382a79"}, + {file = "ddtrace-1.15.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:2f7649c24a7463be9b86d5f11ac6eaa2014896eaf409e67f3dc813a6bb0ed8b6"}, + {file = "ddtrace-1.15.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:dbdbc5bf3b2b56b8e61b241ee372d897b295344e269475f38e837c9bfe03ae2c"}, + {file = "ddtrace-1.15.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:23d39c72ad1844977a80d79206d773c3ec1f1346816b9e45427c25ef88597b4e"}, + {file = "ddtrace-1.15.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:da458bbbc4de14dd8e8f60aefe42a66c551a9f50c69c6e361acc7edab579a3e4"}, + {file = "ddtrace-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d07bb0c50d2df7ff9281bea83534db5127cee8ac2f94111c9544d03d49f60613"}, + {file = "ddtrace-1.15.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:499b3e3d0359e492792ecf8ab6efcf4b1991fbaa523338774333e9a2a66d9d37"}, + {file = "ddtrace-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedd0937f83e0d7b261960365fec5771f39ced599c90f589548a1738a586799d"}, + {file = "ddtrace-1.15.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7643d20991cd7e1c21e65d8b5c292a9dca8d124f69f9e96cc2b5fb8d47802c3a"}, + {file = "ddtrace-1.15.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3f6bb76fe33c2e4842236036f78b1bbdd4da0f2b846627ca7d72b01ac49b3076"}, + {file = "ddtrace-1.15.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ebc9b89501c8a557dab43170e4a12e90358130413a87a0276ccaa0038b0636a4"}, + {file = "ddtrace-1.15.2-cp310-cp310-win32.whl", hash = "sha256:c10ca0e3a63310d314ec7fa55d53f4b4434f06c4d321d64d757814679161bf5d"}, + {file = "ddtrace-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:6208635442ea52ff3f97b9fc64ac25772cda8f105a607a385e55bf524bceefc5"}, + {file = "ddtrace-1.15.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8524f460be02b402f63b11ad3b1177955c8608f814e1758b87f53f15bf9a7599"}, + {file = "ddtrace-1.15.2-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5a2dd127a65e12189055818ab72d44d80587acaaf450c65624e0482d63ff9970"}, + {file = "ddtrace-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3350c647120fbc3355eb35ce054c88e63bc073d71949f377d59b1152a2ed0f4"}, + {file = "ddtrace-1.15.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:adb76713207f0ef688f68a539f9cb63e19cd149d48d36befb835f67f49395ed7"}, + {file = "ddtrace-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8ff5c250c5abfbbbd76a7d3167308a2373ad7e55ecf3c7c26a62fcd2be8a57"}, + {file = "ddtrace-1.15.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:264bed998870b63f548b96f57dd771014cd02ef0b21bb382e745900a7b72ef28"}, + {file = "ddtrace-1.15.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:20bfd8db155167d2ccfddc25b50649338534b12cb00f7ed08514af1eb6a4956e"}, + {file = "ddtrace-1.15.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:72479172bd10f5998188a05b0b4a109ccb2a93467a0aa1e6656d5396c83fb253"}, + {file = "ddtrace-1.15.2-cp311-cp311-win32.whl", hash = "sha256:23bee3d0eb971cc1565caa429620b82f2d69ef648e9c792046b9481188dba9ab"}, + {file = "ddtrace-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:65a29d23ecfbc7cc4ca1069a5586aa836ae3978e64251414933432078bc29bc2"}, + {file = "ddtrace-1.15.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:3a2852da4a76503211ca8b77a50fc86df36ba15fab04b45a6a17faa386f53839"}, + {file = "ddtrace-1.15.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:244180c6decb244c7fda929dc5969b3a510e5a4857239063de1fae139fac9837"}, + {file = "ddtrace-1.15.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:46f9ba0c282a62953f03d1add8eae8c80613244bb93a1ff997dad71d07ce6c72"}, + {file = "ddtrace-1.15.2-cp35-cp35m-win32.whl", hash = "sha256:a39dbf1ca657cc3a876143301e5d775e2f9bcf2ed1e9b4366fb3cf9d6a345a82"}, + {file = "ddtrace-1.15.2-cp35-cp35m-win_amd64.whl", hash = "sha256:7cfd9514e82871321e86897fe567c7548fc45da523df591f3e5adc6633a5781c"}, + {file = "ddtrace-1.15.2-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:3a2978b07d19d4ebf936fde1e455c61b3d88f103f1f9e360b9269fe1a1dc608a"}, + {file = "ddtrace-1.15.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e7795a7f65a6e844ab57a0b31d400e79c4a1f69d174fab8edc69e6d2db56962"}, + {file = "ddtrace-1.15.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aae5306b3b0ec48cb8ade3362629c31bd25999244addff0f4a2f6f3934509894"}, + {file = "ddtrace-1.15.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14fb33bd6d9fa70638d43de7b5170e1c9961d3fbc277314609941e108c45716d"}, + {file = "ddtrace-1.15.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:745ce3c9559fa331ef30208ff1ccaafe3ab3c02f2e01177c560c94acd6f4de27"}, + {file = "ddtrace-1.15.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7706d35215d2cca0a89581ec11da56e25742914ae0865b928034ee9ad7278cf3"}, + {file = "ddtrace-1.15.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0bc18e900d1495deb61093f1af38d94af6a1ca66dd541fd47bd093c3f3b80b4a"}, + {file = "ddtrace-1.15.2-cp36-cp36m-win32.whl", hash = "sha256:b13f4042ef3f391714aca5ca1f03ff3c24c1d201ab5af02f0405335aa5602ff5"}, + {file = "ddtrace-1.15.2-cp36-cp36m-win_amd64.whl", hash = "sha256:eb32e3b3d0f472447b3d427a075007135b3c39488c1fe0f1e097863f326a439b"}, + {file = "ddtrace-1.15.2-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:0953fd9a2555801d68674bb4905f64805efe1e02b3f11def21eb7655be046717"}, + {file = "ddtrace-1.15.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9436ec9cc00b70730d2c1777f11aca7f4863a49ddd27d0b1478e84c1a7667b6f"}, + {file = "ddtrace-1.15.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7215b21c1eaf56b38bf46c66193db3736ecadeb9ae1b9ca780a91addbaa9853"}, + {file = "ddtrace-1.15.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a5f7155b99fe9393bfa4f0e4ef2610ddf59e70aefcf99a95acae8b31e29cc4"}, + {file = "ddtrace-1.15.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:df103a600c2901dc54929ef58dee41887a0bb558efbf7e41a7489bd6264fcf44"}, + {file = "ddtrace-1.15.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d51a73238ad8ceff4232ffa94b860d61187b325e7fab746044dafa312d6bc415"}, + {file = "ddtrace-1.15.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bfc5777204c0c34465fc4ce38d8d1268d9f95ffcbf7e4025e9a5d3e87d3e17c3"}, + {file = "ddtrace-1.15.2-cp37-cp37m-win32.whl", hash = "sha256:9516dbfc974af9632d75e9c32b38e695b88ea18ebfa4580dd0f768bc05272fba"}, + {file = "ddtrace-1.15.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a510252a3d5be6c29db2c69cbd2535268532e8d568fae06b295a06041e1b969d"}, + {file = "ddtrace-1.15.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:82995243719c87aefc85d7df0e1ae61bba8ae1f805d48cbaf2132beb215f1968"}, + {file = "ddtrace-1.15.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:ca5dd51910a81451d236fccdbf5d3ca8e284aa3be56f08db92644f85ef88c56e"}, + {file = "ddtrace-1.15.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d76f485769c035df3ede4ad9830bac06aa8b69ac4617f2eb1251b1094468009"}, + {file = "ddtrace-1.15.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4dd5f5e477021b8810b2b685e1e16ba5a99f31239e22abc71794688b7f3e6e4d"}, + {file = "ddtrace-1.15.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4ec73676c60cc3cf08430f19a59daccbbb5770edc74ad15a99bf4237a40d0fb"}, + {file = "ddtrace-1.15.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6b140f11b89d902174df05e8b9c1eb1b522a63e6c60c5d68ccac8913bb371bbb"}, + {file = "ddtrace-1.15.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c7c8a0e140d28e49cf8cd96cdec8e17232c5525ed5c154729b8afb6cb93a8e2b"}, + {file = "ddtrace-1.15.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0112d258c3a681a63e5f057b9e3ee8504b60d773d95baf195462d9ff4096caa9"}, + {file = "ddtrace-1.15.2-cp38-cp38-win32.whl", hash = "sha256:6ea7b80eb8019a70c999ef8cfd34fd6078a2ae154007d124d5e642531bf1a9d6"}, + {file = "ddtrace-1.15.2-cp38-cp38-win_amd64.whl", hash = "sha256:282b8c9b46d7a8450325299cf348a0f1d8f9f34d174a0ea402bc1a1df4ad7cf3"}, + {file = "ddtrace-1.15.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:53b171404b59c1e030ea614e194d1483fb42437a02ffdd7f4a45175613dd7cb4"}, + {file = "ddtrace-1.15.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9ba06236dd8bd64776b7b734dd9421709670fef090857448e75c97acb30cdce7"}, + {file = "ddtrace-1.15.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6abe5ba4396c9f7633cab68d0e81c5fd94f7c77b046b3ee969eded068a522d7"}, + {file = "ddtrace-1.15.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61a1b48f97a07e2f422ec01bb23861716300cebe4afd917ab36bb4db68904da4"}, + {file = "ddtrace-1.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86e186dc66802e2d71b94330c1635fd4c3f881a1bb71747be162a57b7602daaa"}, + {file = "ddtrace-1.15.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:762b5a0777454299c4ac62177578969ed551c973063f87a8825d9d073e5250ce"}, + {file = "ddtrace-1.15.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:889d359f4382fde41893ba5c00b412cbea8502e1b6bb6c83bf87fa6e63cbfabe"}, + {file = "ddtrace-1.15.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c4d3c9ce3456181e535b9da42bde7c850dc7224039fd083e95b05010c2ff9748"}, + {file = "ddtrace-1.15.2-cp39-cp39-win32.whl", hash = "sha256:69e47d28327a7afb263c16cc6bf1227e1b2bf1fdb2d559dce913a138a3f36807"}, + {file = "ddtrace-1.15.2-cp39-cp39-win_amd64.whl", hash = "sha256:da780fbfe6dd749ee571a468b8e86f1fd4f51626d35626c2356f8a440efe0dfa"}, + {file = "ddtrace-1.15.2.tar.gz", hash = "sha256:e5c1a5965ea8d8260586769102d79522bc7d9758a271252bb58ee05d6c5cd9a8"}, +] + +[package.dependencies] +attrs = {version = ">=20", markers = "python_version > \"2.7\""} +bytecode = [ + {version = ">=0.13.0,<0.14.0", markers = "python_version == \"3.7\""}, + {version = "*", markers = "python_version >= \"3.8\""}, +] +cattrs = {version = "*", markers = "python_version >= \"3.7\""} +ddsketch = ">=2.0.1" +envier = "*" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +opentelemetry-api = {version = ">=1", markers = "python_version >= \"3.7\""} +protobuf = {version = ">=3", markers = "python_version >= \"3.7\""} +six = ">=1.12.0" +typing-extensions = "*" +xmltodict = ">=0.12" + +[package.extras] +opentracing = ["opentracing (>=2.0.0)"] + [[package]] name = "decorator" version = "5.1.1" @@ -609,6 +782,37 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + +[[package]] +name = "envier" +version = "0.4.0" +description = "Python application configuration via the environment" +optional = false +python-versions = ">=2.7" +files = [ + {file = "envier-0.4.0-py3-none-any.whl", hash = "sha256:7b91af0f16ea3e56d91ec082f038987e81b441fc19c657a8b8afe0909740a706"}, + {file = "envier-0.4.0.tar.gz", hash = "sha256:e68dcd1ed67d8b6313883e27dff3e701b7fba944d2ed4b7f53d0cc2e12364a82"}, +] + +[package.extras] +mypy = ["mypy"] + [[package]] name = "exceptiongroup" version = "1.1.2" @@ -1005,13 +1209,13 @@ pbr = "*" [[package]] name = "jsii" -version = "1.85.0" +version = "1.86.1" description = "Python client for jsii runtime" optional = false python-versions = "~=3.7" files = [ - {file = "jsii-1.85.0-py3-none-any.whl", hash = "sha256:379feb1a1a3c4e449307564f42a7cddef05e43760cbfbbfe8434f6448cd668a0"}, - {file = "jsii-1.85.0.tar.gz", hash = "sha256:b77194cf053c06c6bdffc887a4d1d2a41113c6f4780a7d78d70a780a70998008"}, + {file = "jsii-1.86.1-py3-none-any.whl", hash = "sha256:32eb46ed4c9a35bc92b892ef049ed1996f13be38ffef964d607e8fe930471b3e"}, + {file = "jsii-1.86.1.tar.gz", hash = "sha256:44f9a820eea92c9508693f72d3129b5a080421c949c32303f4f7b2cc98a81f59"}, ] [package.dependencies] @@ -1288,13 +1492,13 @@ test = ["coverage", "flake8 (>=3.0)", "shtab"] [[package]] name = "mkdocs" -version = "1.5.1" +version = "1.5.2" description = "Project documentation with Markdown." optional = false python-versions = ">=3.7" files = [ - {file = "mkdocs-1.5.1-py3-none-any.whl", hash = "sha256:67e889f8d8ba1fe5decdfc59f5f8f21d6a8925a129339e93dede303bdea03a98"}, - {file = "mkdocs-1.5.1.tar.gz", hash = "sha256:f2f323c62fffdf1b71b84849e39aef56d6852b3f0a5571552bca32cefc650209"}, + {file = "mkdocs-1.5.2-py3-none-any.whl", hash = "sha256:60a62538519c2e96fe8426654a67ee177350451616118a41596ae7c876bb7eac"}, + {file = "mkdocs-1.5.2.tar.gz", hash = "sha256:70d0da09c26cff288852471be03c23f0f521fc15cf16ac89c7a3bfb9ae8d24f9"}, ] [package.dependencies] @@ -1613,6 +1817,21 @@ doc = ["nb2plots (>=0.6)", "numpydoc (>=1.1)", "pillow (>=8.2)", "pydata-sphinx- extra = ["lxml (>=4.5)", "pydot (>=1.4.1)", "pygraphviz (>=1.7)"] test = ["codecov (>=2.1)", "pytest (>=6.2)", "pytest-cov (>=2.12)"] +[[package]] +name = "opentelemetry-api" +version = "1.19.0" +description = "OpenTelemetry Python API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "opentelemetry_api-1.19.0-py3-none-any.whl", hash = "sha256:dcd2a0ad34b691964947e1d50f9e8c415c32827a1d87f0459a72deb9afdf5597"}, + {file = "opentelemetry_api-1.19.0.tar.gz", hash = "sha256:db374fb5bea00f3c7aa290f5d94cea50b659e6ea9343384c5f6c2bb5d5e8db65"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +importlib-metadata = ">=6.0,<7.0" + [[package]] name = "packaging" version = "23.1" @@ -1708,6 +1927,28 @@ importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "protobuf" +version = "4.24.0" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "protobuf-4.24.0-cp310-abi3-win32.whl", hash = "sha256:81cb9c4621d2abfe181154354f63af1c41b00a4882fb230b4425cbaed65e8f52"}, + {file = "protobuf-4.24.0-cp310-abi3-win_amd64.whl", hash = "sha256:6c817cf4a26334625a1904b38523d1b343ff8b637d75d2c8790189a4064e51c3"}, + {file = "protobuf-4.24.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:ae97b5de10f25b7a443b40427033e545a32b0e9dda17bcd8330d70033379b3e5"}, + {file = "protobuf-4.24.0-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:567fe6b0647494845d0849e3d5b260bfdd75692bf452cdc9cb660d12457c055d"}, + {file = "protobuf-4.24.0-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:a6b1ca92ccabfd9903c0c7dde8876221dc7d8d87ad5c42e095cc11b15d3569c7"}, + {file = "protobuf-4.24.0-cp37-cp37m-win32.whl", hash = "sha256:a38400a692fd0c6944c3c58837d112f135eb1ed6cdad5ca6c5763336e74f1a04"}, + {file = "protobuf-4.24.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5ab19ee50037d4b663c02218a811a5e1e7bb30940c79aac385b96e7a4f9daa61"}, + {file = "protobuf-4.24.0-cp38-cp38-win32.whl", hash = "sha256:e8834ef0b4c88666ebb7c7ec18045aa0f4325481d724daa624a4cf9f28134653"}, + {file = "protobuf-4.24.0-cp38-cp38-win_amd64.whl", hash = "sha256:8bb52a2be32db82ddc623aefcedfe1e0eb51da60e18fcc908fb8885c81d72109"}, + {file = "protobuf-4.24.0-cp39-cp39-win32.whl", hash = "sha256:ae7a1835721086013de193311df858bc12cd247abe4ef9710b715d930b95b33e"}, + {file = "protobuf-4.24.0-cp39-cp39-win_amd64.whl", hash = "sha256:44825e963008f8ea0d26c51911c30d3e82e122997c3c4568fd0385dd7bacaedf"}, + {file = "protobuf-4.24.0-py3-none-any.whl", hash = "sha256:82e6e9ebdd15b8200e8423676eab38b774624d6a1ad696a60d86a2ac93f18201"}, + {file = "protobuf-4.24.0.tar.gz", hash = "sha256:5d0ceb9de6e08311832169e601d1fc71bd8e8c779f3ee38a97a78554945ecb85"}, +] + [[package]] name = "publication" version = "0.0.3" @@ -1784,13 +2025,13 @@ email = ["email-validator (>=1.0.3)"] [[package]] name = "pygments" -version = "2.15.1" +version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, - {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, ] [package.extras] @@ -2069,99 +2310,99 @@ mando = ">=0.6,<0.7" [[package]] name = "regex" -version = "2023.6.3" +version = "2023.8.8" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.6" files = [ - {file = "regex-2023.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd"}, - {file = "regex-2023.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef"}, - {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc"}, - {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef"}, - {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8"}, - {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06"}, - {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d"}, - {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536"}, - {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2"}, - {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222"}, - {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2"}, - {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18"}, - {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568"}, - {file = "regex-2023.6.3-cp310-cp310-win32.whl", hash = "sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1"}, - {file = "regex-2023.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0"}, - {file = "regex-2023.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969"}, - {file = "regex-2023.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa"}, - {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e"}, - {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df"}, - {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c"}, - {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8"}, - {file = "regex-2023.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9"}, - {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c"}, - {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7"}, - {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f"}, - {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461"}, - {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477"}, - {file = "regex-2023.6.3-cp311-cp311-win32.whl", hash = "sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9"}, - {file = "regex-2023.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af"}, - {file = "regex-2023.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525"}, - {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697"}, - {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd"}, - {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9"}, - {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693"}, - {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14"}, - {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f"}, - {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e"}, - {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3"}, - {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1"}, - {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1"}, - {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787"}, - {file = "regex-2023.6.3-cp36-cp36m-win32.whl", hash = "sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54"}, - {file = "regex-2023.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27"}, - {file = "regex-2023.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487"}, - {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3"}, - {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16"}, - {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3"}, - {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3"}, - {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc"}, - {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019"}, - {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777"}, - {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee"}, - {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591"}, - {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0"}, - {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb"}, - {file = "regex-2023.6.3-cp37-cp37m-win32.whl", hash = "sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7"}, - {file = "regex-2023.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23"}, - {file = "regex-2023.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07"}, - {file = "regex-2023.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289"}, - {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c"}, - {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036"}, - {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7"}, - {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d"}, - {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2"}, - {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff"}, - {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82"}, - {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06"}, - {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f"}, - {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747"}, - {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9"}, - {file = "regex-2023.6.3-cp38-cp38-win32.whl", hash = "sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88"}, - {file = "regex-2023.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72"}, - {file = "regex-2023.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751"}, - {file = "regex-2023.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68"}, - {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf"}, - {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a"}, - {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1"}, - {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6"}, - {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77"}, - {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9"}, - {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd"}, - {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938"}, - {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7"}, - {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac"}, - {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd"}, - {file = "regex-2023.6.3-cp39-cp39-win32.whl", hash = "sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f"}, - {file = "regex-2023.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a"}, - {file = "regex-2023.6.3.tar.gz", hash = "sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0"}, + {file = "regex-2023.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:88900f521c645f784260a8d346e12a1590f79e96403971241e64c3a265c8ecdb"}, + {file = "regex-2023.8.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3611576aff55918af2697410ff0293d6071b7e00f4b09e005d614686ac4cd57c"}, + {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8a0ccc8f2698f120e9e5742f4b38dc944c38744d4bdfc427616f3a163dd9de5"}, + {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c662a4cbdd6280ee56f841f14620787215a171c4e2d1744c9528bed8f5816c96"}, + {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf0633e4a1b667bfe0bb10b5e53fe0d5f34a6243ea2530eb342491f1adf4f739"}, + {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551ad543fa19e94943c5b2cebc54c73353ffff08228ee5f3376bd27b3d5b9800"}, + {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54de2619f5ea58474f2ac211ceea6b615af2d7e4306220d4f3fe690c91988a61"}, + {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ec4b3f0aebbbe2fc0134ee30a791af522a92ad9f164858805a77442d7d18570"}, + {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ae646c35cb9f820491760ac62c25b6d6b496757fda2d51be429e0e7b67ae0ab"}, + {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca339088839582d01654e6f83a637a4b8194d0960477b9769d2ff2cfa0fa36d2"}, + {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:d9b6627408021452dcd0d2cdf8da0534e19d93d070bfa8b6b4176f99711e7f90"}, + {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:bd3366aceedf274f765a3a4bc95d6cd97b130d1dda524d8f25225d14123c01db"}, + {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7aed90a72fc3654fba9bc4b7f851571dcc368120432ad68b226bd593f3f6c0b7"}, + {file = "regex-2023.8.8-cp310-cp310-win32.whl", hash = "sha256:80b80b889cb767cc47f31d2b2f3dec2db8126fbcd0cff31b3925b4dc6609dcdb"}, + {file = "regex-2023.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:b82edc98d107cbc7357da7a5a695901b47d6eb0420e587256ba3ad24b80b7d0b"}, + {file = "regex-2023.8.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1e7d84d64c84ad97bf06f3c8cb5e48941f135ace28f450d86af6b6512f1c9a71"}, + {file = "regex-2023.8.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce0f9fbe7d295f9922c0424a3637b88c6c472b75eafeaff6f910494a1fa719ef"}, + {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06c57e14ac723b04458df5956cfb7e2d9caa6e9d353c0b4c7d5d54fcb1325c46"}, + {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a9aaa5a1267125eef22cef3b63484c3241aaec6f48949b366d26c7250e0357"}, + {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b7408511fca48a82a119d78a77c2f5eb1b22fe88b0d2450ed0756d194fe7a9a"}, + {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14dc6f2d88192a67d708341f3085df6a4f5a0c7b03dec08d763ca2cd86e9f559"}, + {file = "regex-2023.8.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48c640b99213643d141550326f34f0502fedb1798adb3c9eb79650b1ecb2f177"}, + {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0085da0f6c6393428bf0d9c08d8b1874d805bb55e17cb1dfa5ddb7cfb11140bf"}, + {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:964b16dcc10c79a4a2be9f1273fcc2684a9eedb3906439720598029a797b46e6"}, + {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7ce606c14bb195b0e5108544b540e2c5faed6843367e4ab3deb5c6aa5e681208"}, + {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:40f029d73b10fac448c73d6eb33d57b34607f40116e9f6e9f0d32e9229b147d7"}, + {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3b8e6ea6be6d64104d8e9afc34c151926f8182f84e7ac290a93925c0db004bfd"}, + {file = "regex-2023.8.8-cp311-cp311-win32.whl", hash = "sha256:942f8b1f3b223638b02df7df79140646c03938d488fbfb771824f3d05fc083a8"}, + {file = "regex-2023.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:51d8ea2a3a1a8fe4f67de21b8b93757005213e8ac3917567872f2865185fa7fb"}, + {file = "regex-2023.8.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e951d1a8e9963ea51efd7f150450803e3b95db5939f994ad3d5edac2b6f6e2b4"}, + {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704f63b774218207b8ccc6c47fcef5340741e5d839d11d606f70af93ee78e4d4"}, + {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22283c769a7b01c8ac355d5be0715bf6929b6267619505e289f792b01304d898"}, + {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91129ff1bb0619bc1f4ad19485718cc623a2dc433dff95baadbf89405c7f6b57"}, + {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de35342190deb7b866ad6ba5cbcccb2d22c0487ee0cbb251efef0843d705f0d4"}, + {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b993b6f524d1e274a5062488a43e3f9f8764ee9745ccd8e8193df743dbe5ee61"}, + {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3026cbcf11d79095a32d9a13bbc572a458727bd5b1ca332df4a79faecd45281c"}, + {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:293352710172239bf579c90a9864d0df57340b6fd21272345222fb6371bf82b3"}, + {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d909b5a3fff619dc7e48b6b1bedc2f30ec43033ba7af32f936c10839e81b9217"}, + {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3d370ff652323c5307d9c8e4c62efd1956fb08051b0e9210212bc51168b4ff56"}, + {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:b076da1ed19dc37788f6a934c60adf97bd02c7eea461b73730513921a85d4235"}, + {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e9941a4ada58f6218694f382e43fdd256e97615db9da135e77359da257a7168b"}, + {file = "regex-2023.8.8-cp36-cp36m-win32.whl", hash = "sha256:a8c65c17aed7e15a0c824cdc63a6b104dfc530f6fa8cb6ac51c437af52b481c7"}, + {file = "regex-2023.8.8-cp36-cp36m-win_amd64.whl", hash = "sha256:aadf28046e77a72f30dcc1ab185639e8de7f4104b8cb5c6dfa5d8ed860e57236"}, + {file = "regex-2023.8.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:423adfa872b4908843ac3e7a30f957f5d5282944b81ca0a3b8a7ccbbfaa06103"}, + {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ae594c66f4a7e1ea67232a0846649a7c94c188d6c071ac0210c3e86a5f92109"}, + {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e51c80c168074faa793685656c38eb7a06cbad7774c8cbc3ea05552d615393d8"}, + {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09b7f4c66aa9d1522b06e31a54f15581c37286237208df1345108fcf4e050c18"}, + {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e73e5243af12d9cd6a9d6a45a43570dbe2e5b1cdfc862f5ae2b031e44dd95a8"}, + {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941460db8fe3bd613db52f05259c9336f5a47ccae7d7def44cc277184030a116"}, + {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f0ccf3e01afeb412a1a9993049cb160d0352dba635bbca7762b2dc722aa5742a"}, + {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2e9216e0d2cdce7dbc9be48cb3eacb962740a09b011a116fd7af8c832ab116ca"}, + {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5cd9cd7170459b9223c5e592ac036e0704bee765706445c353d96f2890e816c8"}, + {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4873ef92e03a4309b3ccd8281454801b291b689f6ad45ef8c3658b6fa761d7ac"}, + {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:239c3c2a339d3b3ddd51c2daef10874410917cd2b998f043c13e2084cb191684"}, + {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1005c60ed7037be0d9dea1f9c53cc42f836188227366370867222bda4c3c6bd7"}, + {file = "regex-2023.8.8-cp37-cp37m-win32.whl", hash = "sha256:e6bd1e9b95bc5614a7a9c9c44fde9539cba1c823b43a9f7bc11266446dd568e3"}, + {file = "regex-2023.8.8-cp37-cp37m-win_amd64.whl", hash = "sha256:9a96edd79661e93327cfeac4edec72a4046e14550a1d22aa0dd2e3ca52aec921"}, + {file = "regex-2023.8.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2181c20ef18747d5f4a7ea513e09ea03bdd50884a11ce46066bb90fe4213675"}, + {file = "regex-2023.8.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a2ad5add903eb7cdde2b7c64aaca405f3957ab34f16594d2b78d53b8b1a6a7d6"}, + {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9233ac249b354c54146e392e8a451e465dd2d967fc773690811d3a8c240ac601"}, + {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:920974009fb37b20d32afcdf0227a2e707eb83fe418713f7a8b7de038b870d0b"}, + {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2b6c5dfe0929b6c23dde9624483380b170b6e34ed79054ad131b20203a1a63"}, + {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96979d753b1dc3b2169003e1854dc67bfc86edf93c01e84757927f810b8c3c93"}, + {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ae54a338191e1356253e7883d9d19f8679b6143703086245fb14d1f20196be9"}, + {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2162ae2eb8b079622176a81b65d486ba50b888271302190870b8cc488587d280"}, + {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c884d1a59e69e03b93cf0dfee8794c63d7de0ee8f7ffb76e5f75be8131b6400a"}, + {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf9273e96f3ee2ac89ffcb17627a78f78e7516b08f94dc435844ae72576a276e"}, + {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:83215147121e15d5f3a45d99abeed9cf1fe16869d5c233b08c56cdf75f43a504"}, + {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f7454aa427b8ab9101f3787eb178057c5250478e39b99540cfc2b889c7d0586"}, + {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0640913d2c1044d97e30d7c41728195fc37e54d190c5385eacb52115127b882"}, + {file = "regex-2023.8.8-cp38-cp38-win32.whl", hash = "sha256:0c59122ceccb905a941fb23b087b8eafc5290bf983ebcb14d2301febcbe199c7"}, + {file = "regex-2023.8.8-cp38-cp38-win_amd64.whl", hash = "sha256:c12f6f67495ea05c3d542d119d270007090bad5b843f642d418eb601ec0fa7be"}, + {file = "regex-2023.8.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82cd0a69cd28f6cc3789cc6adeb1027f79526b1ab50b1f6062bbc3a0ccb2dbc3"}, + {file = "regex-2023.8.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bb34d1605f96a245fc39790a117ac1bac8de84ab7691637b26ab2c5efb8f228c"}, + {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:987b9ac04d0b38ef4f89fbc035e84a7efad9cdd5f1e29024f9289182c8d99e09"}, + {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dd6082f4e2aec9b6a0927202c85bc1b09dcab113f97265127c1dc20e2e32495"}, + {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7eb95fe8222932c10d4436e7a6f7c99991e3fdd9f36c949eff16a69246dee2dc"}, + {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7098c524ba9f20717a56a8d551d2ed491ea89cbf37e540759ed3b776a4f8d6eb"}, + {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b694430b3f00eb02c594ff5a16db30e054c1b9589a043fe9174584c6efa8033"}, + {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2aeab3895d778155054abea5238d0eb9a72e9242bd4b43f42fd911ef9a13470"}, + {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:988631b9d78b546e284478c2ec15c8a85960e262e247b35ca5eaf7ee22f6050a"}, + {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:67ecd894e56a0c6108ec5ab1d8fa8418ec0cff45844a855966b875d1039a2e34"}, + {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:14898830f0a0eb67cae2bbbc787c1a7d6e34ecc06fbd39d3af5fe29a4468e2c9"}, + {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f2200e00b62568cfd920127782c61bc1c546062a879cdc741cfcc6976668dfcf"}, + {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9691a549c19c22d26a4f3b948071e93517bdf86e41b81d8c6ac8a964bb71e5a6"}, + {file = "regex-2023.8.8-cp39-cp39-win32.whl", hash = "sha256:6ab2ed84bf0137927846b37e882745a827458689eb969028af8032b1b3dac78e"}, + {file = "regex-2023.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:5543c055d8ec7801901e1193a51570643d6a6ab8751b1f7dd9af71af467538bb"}, + {file = "regex-2023.8.8.tar.gz", hash = "sha256:fcbdc5f2b0f1cd0f6a56cdb46fe41d2cce1e644e3b68832f3eeebc5fb0f7712e"}, ] [[package]] @@ -2575,7 +2816,7 @@ watchmedo = ["PyYAML (>=3.10)"] name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." -optional = true +optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, @@ -2671,6 +2912,17 @@ PyYAML = ">=4.2b1,<7.0" radon = ">=4,<6" requests = ">=2.0,<3.0" +[[package]] +name = "xmltodict" +version = "0.13.0" +description = "Makes working with XML feel like you are working with JSON" +optional = false +python-versions = ">=3.4" +files = [ + {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"}, + {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"}, +] + [[package]] name = "zipp" version = "3.15.0" @@ -2689,6 +2941,7 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [extras] all = ["aws-xray-sdk", "fastjsonschema", "pydantic"] aws-sdk = ["boto3"] +datadog = [] parser = ["pydantic"] tracer = ["aws-xray-sdk"] validation = ["fastjsonschema"] @@ -2696,4 +2949,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "bda535adaf225acfc4e90829893a0f7677761596824fd3c8e6bea4ff24fad07a" +content-hash = "d99019198a55e402af3251eb826136b743dcced7df7faa84c1b920f009dd4dbf" diff --git a/pyproject.toml b/pyproject.toml index 51cab19741c..04998e0da56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,7 @@ ijson = "^3.2.2" typed-ast = { version = "^1.5.5", python = "< 3.8"} hvac = "^1.1.1" aws-requests-auth = "^0.4.3" +datadog-lambda = "^4.77.0" [tool.poetry.extras] parser = ["pydantic"] @@ -84,6 +85,7 @@ tracer = ["aws-xray-sdk"] all = ["pydantic", "aws-xray-sdk", "fastjsonschema"] # allow customers to run code locally without emulators (SAM CLI, etc.) aws-sdk = ["boto3"] +datadog=["datadog-lambda"] [tool.poetry.group.dev.dependencies] cfn-lint = "0.79.6" diff --git a/tests/functional/metrics/conftest.py b/tests/functional/metrics/conftest.py index cb0e083ca1f..2de3a0087c2 100644 --- a/tests/functional/metrics/conftest.py +++ b/tests/functional/metrics/conftest.py @@ -29,6 +29,11 @@ def metric() -> Dict[str, str]: return {"name": "single_metric", "unit": MetricUnit.Count, "value": 1} +@pytest.fixture +def metric_datadog() -> Dict[str, str]: + return {"name": "single_metric", "value": 1, "timestamp": 1691678198, "powertools": "datadog"} + + @pytest.fixture def metrics() -> List[Dict[str, str]]: return [ diff --git a/tests/functional/metrics/test_metrics_datadog.py b/tests/functional/metrics/test_metrics_datadog.py new file mode 100644 index 00000000000..c81c825f656 --- /dev/null +++ b/tests/functional/metrics/test_metrics_datadog.py @@ -0,0 +1,281 @@ +import json +import warnings +from collections import namedtuple + +import pytest +from test_metrics_provider import capture_metrics_output + +from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError +from aws_lambda_powertools.metrics.provider.cold_start import reset_cold_start_flag +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics, DatadogProvider + + +def test_datadog_coldstart(capsys): + reset_cold_start_flag() + + # GIVEN DatadogMetrics is initialized + dd_provider = DatadogProvider(flush_to_log=True) + metrics = DatadogMetrics(provider=dd_provider) + + LambdaContext = namedtuple("LambdaContext", "function_name") + + # WHEN log_metrics is used with capture_cold_start_metric + @metrics.log_metrics(capture_cold_start_metric=True) + def lambda_handler(event, context): + metrics.add_metric(name="item_sold", value=1, product="latte", order="online") + + lambda_handler({}, LambdaContext("example_fn2")) + logs = capsys.readouterr().out.strip() + + # THEN ColdStart metric and function_name and service dimension should be logged + assert "ColdStart" in logs + assert "example_fn2" in logs + + +def test_datadog_write_to_log_with_env_variable(capsys, monkeypatch): + # GIVEN DD_FLUSH_TO_LOG env is configured + monkeypatch.setenv("DD_FLUSH_TO_LOG", "True") + metrics = DatadogMetrics() + + # WHEN we add a metric + metrics.add_metric(name="item_sold", value=1, product="latte", order="online") + metrics.flush_metrics() + logs = capture_metrics_output(capsys) + + # THEN metrics is flushed to log + logs["e"] = "" + assert logs == json.loads('{"m":"item_sold","v":1,"e":"","t":["product:latte","order:online"]}') + + +def test_datadog_with_invalid_metric_value(): + # GIVEN DatadogMetrics is initialized + metrics = DatadogMetrics() + + # WHEN we pass an incorrect metric value (non-numeric) + # WHEN we attempt to serialize a valid Datadog metric + # THEN it should fail validation and raise MetricValueError + with pytest.raises(MetricValueError, match=".*is not a valid number"): + metrics.add_metric(name="item_sold", value="a", product="latte", order="online") + + +def test_datadog_with_invalid_metric_name(): + # GIVEN DatadogMetrics is initialized + metrics = DatadogMetrics() + + # WHEN we a metric name starting with a number + # WHEN we attempt to serialize a valid Datadog metric + # THEN it should fail validation and raise MetricValueError + with pytest.raises(SchemaValidationError, match="Invalid metric name.*"): + metrics.add_metric(name="1_item_sold", value="a", product="latte", order="online") + + +def test_datadog_raise_on_empty(): + # GIVEN DatadogMetrics is initialized + metrics = DatadogMetrics() + + LambdaContext = namedtuple("LambdaContext", "function_name") + + # WHEN we set raise_on_empty_metrics to True + @metrics.log_metrics(raise_on_empty_metrics=True) + def lambda_handler(event, context): + pass + + # THEN it should fail with no metric serialized + with pytest.raises(SchemaValidationError, match="Must contain at least one metric."): + lambda_handler({}, LambdaContext("example_fn")) + + +def test_datadog_tags_using_kwargs(capsys): + # GIVEN DatadogMetrics is initialized + metrics = DatadogMetrics(flush_to_log=True) + + # WHEN we add tags using kwargs + metrics.add_metric("order_valve", 12.45, sales="sam") + metrics.flush_metrics() + logs = capsys.readouterr().out.strip() + log_dict = json.loads(logs) + tag_list = log_dict.get("t") + + # THEN tags must be present + assert "sales:sam" in tag_list + + +def test_metrics_clear_metrics_after_invocation(metric_datadog): + # GIVEN DatadogMetrics is initialized + my_metrics = DatadogMetrics(flush_to_log=True) + my_metrics.add_metric(**metric_datadog) + + # WHEN log_metrics is used to flush metrics from memory + @my_metrics.log_metrics + def lambda_handler(evt, context): + pass + + lambda_handler({}, {}) + + # THEN metric set should be empty after function has been run + assert my_metrics.metric_set == [] + + +def test_metrics_decorator_with_metrics_warning(): + # GIVEN DatadogMetrics is initialized + my_metrics = DatadogMetrics(flush_to_log=True) + + # WHEN using the log_metrics decorator and no metrics have been added + @my_metrics.log_metrics + def lambda_handler(evt, context): + pass + + # THEN it should raise a warning instead of throwing an exception + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("default") + lambda_handler({}, {}) + assert len(w) == 1 + assert str(w[-1].message) == ( + "No application metrics to publish. The cold-start metric may be published if enabled. " + "If application metrics should never be empty, consider using 'raise_on_empty_metrics'" + ) + + +def test_metrics_with_default_namespace(capsys, namespace): + # GIVEN DatadogMetrics is initialized with default namespace + metrics = DatadogMetrics(flush_to_log=True) + + LambdaContext = namedtuple("LambdaContext", "function_name") + + # WHEN we add metrics + @metrics.log_metrics + def lambda_handler(event, context): + metrics.add_metric(name="item_sold", value=1, product="latte", order="online") + + lambda_handler({}, LambdaContext("example_fn2")) + logs = capsys.readouterr().out.strip() + + # THEN default namespace must be assumed + assert namespace not in logs + + +def test_datadog_with_non_default_namespace(capsys, namespace): + # GIVEN DatadogMetrics is initialized with a non-default namespace + metrics = DatadogMetrics(namespace=namespace, flush_to_log=True) + + LambdaContext = namedtuple("LambdaContext", "function_name") + + # WHEN log_metrics is used + @metrics.log_metrics + def lambda_handler(event, context): + metrics.add_metric(name="item_sold", value=1, product="latte", order="online") + + lambda_handler({}, LambdaContext("example_fn")) + logs = capsys.readouterr().out.strip() + + # THEN namespace must be present in logs + assert namespace in logs + + +def test_serialize_metrics(metric_datadog): + # GIVEN DatadogMetrics is initialized + my_metrics = DatadogMetrics(flush_to_log=True) + my_metrics.add_metric(**metric_datadog) + + # WHEN we serialize metrics + my_metrics.serialize_metric_set() + + # THEN metric set should be empty after function has been run + assert my_metrics.metric_set[0]["m"] == "single_metric" + + +def test_clear_metrics(metric): + # GIVEN DatadogMetrics is initialized + my_metrics = DatadogMetrics(flush_to_log=True) + my_metrics.add_metric(**metric) + my_metrics.clear_metrics() + + # THEN metric set should be empty after function has been run + assert my_metrics.metric_set == [] + + +def test_persist_default_tags(capsys): + # GIVEN DatadogMetrics is initialized and we persist a set of default tags + my_metrics = DatadogMetrics(flush_to_log=True) + my_metrics.set_default_tags(environment="test", log_group="/lambda/test") + + # WHEN we utilize log_metrics to serialize + # and flush metrics and clear all metrics and tags from memory + # at the end of a function execution + @my_metrics.log_metrics + def lambda_handler(evt, ctx): + my_metrics.add_metric(name="item_sold", value=1) + + lambda_handler({}, {}) + first_invocation = capsys.readouterr().out.strip() + + lambda_handler({}, {}) + second_invocation = capsys.readouterr().out.strip() + + # THEN we should have default tags in both outputs + assert "environment" in first_invocation + assert "environment" in second_invocation + + +def test_log_metrics_with_default_tags(capsys): + # GIVEN DatadogMetrics is initialized and we persist a set of default tags + my_metrics = DatadogMetrics(flush_to_log=True) + default_tags = {"environment": "test", "log_group": "/lambda/test"} + + # WHEN we utilize log_metrics with default dimensions to serialize + # and flush metrics and clear all metrics and tags from memory + # at the end of a function execution + @my_metrics.log_metrics(default_tags=default_tags) + def lambda_handler(evt, ctx): + my_metrics.add_metric(name="item_sold", value=1) + + lambda_handler({}, {}) + first_invocation = capsys.readouterr().out.strip() + + lambda_handler({}, {}) + second_invocation = capsys.readouterr().out.strip() + + # THEN we should have default tags in both outputs + assert "environment" in first_invocation + assert "environment" in second_invocation + + +def test_clear_default_tags(): + # GIVEN DatadogMetrics is initialized and we persist a set of default tags + my_metrics = DatadogMetrics() + my_metrics.set_default_tags(environment="test", log_group="/lambda/test") + + # WHEN they are removed via clear_default_tags method + my_metrics.clear_default_tags() + + # THEN there should be no default tags + assert not my_metrics.default_tags + + +def test_namespace_var_precedence(monkeypatch, namespace): + # GIVEN we use POWERTOOLS_METRICS_NAMESPACE + monkeypatch.setenv("POWERTOOLS_METRICS_NAMESPACE", "a_namespace") + my_metrics = DatadogMetrics(namespace=namespace, flush_to_log=True) + + # WHEN creating a metric and explicitly set a namespace + my_metrics.add_metric(name="item_sold", value=1) + + output = my_metrics.serialize_metric_set() + + # THEN namespace should match the explicitly passed variable and not the env var + assert output[0]["m"] == f"{namespace}.item_sold" + + +def test_namespace_env_var(monkeypatch): + # GIVEN POWERTOOLS_METRICS_NAMESPACE is set + env_namespace = "a_namespace" + monkeypatch.setenv("POWERTOOLS_METRICS_NAMESPACE", env_namespace) + my_metrics = DatadogMetrics(flush_to_log=True) + + # WHEN creating a metric and explicitly set a namespace + my_metrics.add_metric(name="item_sold", value=1) + + output = my_metrics.serialize_metric_set() + + # THEN namespace should match the explicitly passed variable and not the env var + assert output[0]["m"] == f"{env_namespace}.item_sold" diff --git a/tests/unit/metrics/conftest.py b/tests/unit/metrics/conftest.py new file mode 100644 index 00000000000..8d601e4d13b --- /dev/null +++ b/tests/unit/metrics/conftest.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest.fixture +def namespace() -> str: + return "test_namespace" diff --git a/tests/unit/metrics/test_functions.py b/tests/unit/metrics/test_functions.py new file mode 100644 index 00000000000..f3414720bba --- /dev/null +++ b/tests/unit/metrics/test_functions.py @@ -0,0 +1,63 @@ +import pytest + +from aws_lambda_powertools.metrics.functions import ( + extract_cloudwatch_metric_resolution_value, + extract_cloudwatch_metric_unit_value, +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import ( + MetricResolutionError, + MetricUnitError, +) +from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit + + +def test_extract_invalid_cloudwatch_metric_resolution_value(): + metric_resolutions = [resolution.value for resolution in MetricResolution] + + # GIVEN an invalid EMF resolution value + resolution = 2 + + # WHEN try to extract this value + # THEN must fail with MetricResolutionError + with pytest.raises(MetricResolutionError, match="Invalid metric resolution.*"): + extract_cloudwatch_metric_resolution_value(metric_resolutions, resolution=resolution) + + +def test_extract_valid_cloudwatch_metric_resolution_value(): + metric_resolutions = [resolution.value for resolution in MetricResolution] + + # GIVEN a valid EMF resolution value + resolution = 1 + + # WHEN try to extract this value + extracted_resolution_value = extract_cloudwatch_metric_resolution_value(metric_resolutions, resolution=resolution) + + # THEN value must be extracted + assert extracted_resolution_value == resolution + + +def test_extract_invalid_cloudwatch_metric_unit_value(): + metric_units = [unit.value for unit in MetricUnit] + metric_unit_valid_options = list(MetricUnit.__members__) + + # GIVEN an invalid EMF unit value + unit = "Fake" + + # WHEN try to extract this value + # THEN must fail with MetricUnitError + with pytest.raises(MetricUnitError, match="Invalid metric unit.*"): + extract_cloudwatch_metric_unit_value(metric_units, metric_unit_valid_options, unit=unit) + + +def test_extract_valid_cloudwatch_metric_unit_value(): + metric_units = [unit.value for unit in MetricUnit] + metric_unit_valid_options = list(MetricUnit.__members__) + + # GIVEN an invalid EMF unit value + unit = "Count" + + # WHEN try to extract this value + extracted_unit_value = extract_cloudwatch_metric_unit_value(metric_units, metric_unit_valid_options, unit=unit) + + # THEN value must be extracted + assert extracted_unit_value == unit diff --git a/tests/unit/metrics/test_unit_datadog.py b/tests/unit/metrics/test_unit_datadog.py new file mode 100644 index 00000000000..ab54e9730fe --- /dev/null +++ b/tests/unit/metrics/test_unit_datadog.py @@ -0,0 +1,69 @@ +import pytest + +from aws_lambda_powertools.metrics.exceptions import SchemaValidationError +from aws_lambda_powertools.metrics.provider.datadog import DatadogMetrics +from aws_lambda_powertools.metrics.provider.datadog.warnings import DatadogDataValidationWarning + + +def test_get_namespace_property(namespace): + # GIVEN DatadogMetrics is initialized + my_metrics = DatadogMetrics(namespace=namespace) + + # WHEN we try to access the namespace property + # THEN namespace property must be present + assert my_metrics.namespace == namespace + + +def test_set_namespace_property(namespace): + # GIVEN DatadogMetrics is initialized + my_metrics = DatadogMetrics() + + # WHEN we set the namespace property after ther initialization + my_metrics.namespace = namespace + + # THEN namespace property must be present + assert my_metrics.namespace == namespace + + +def test_default_tags_across_instances(): + # GIVEN DatadogMetrics is initialized and we persist a set of default tags + my_metrics = DatadogMetrics() + my_metrics.set_default_tags(environment="test", log_group="/lambda/test") + + # WHEN a new DatadogMetrics instance is created + same_metrics = DatadogMetrics() + + # THEN default tags should also be present in the new instance + assert "environment" in same_metrics.default_tags + + +def test_invalid_datadog_metric_name(): + metrics = DatadogMetrics() + + # GIVEN three metrics names with different invalid names + metric_name_1 = "1_metric" # Metric name must not start with number + metric_name_2 = "metric_ç" # Metric name must not contains unicode characters + metric_name_3 = "".join(["x" for _ in range(201)]) # Metric name must have less than 200 characters + + # WHEN we try to validate those metrics names + # THEN must be False + with pytest.raises(SchemaValidationError, match="Invalid metric name.*"): + metrics.add_metric(name=metric_name_1, value=1) + + with pytest.raises(SchemaValidationError, match="Invalid metric name.*"): + metrics.add_metric(name=metric_name_2, value=1) + + with pytest.raises(SchemaValidationError, match="Invalid metric name.*"): + metrics.add_metric(name=metric_name_3, value=1) + + +def test_invalid_datadog_metric_tag(): + metrics = DatadogMetrics() + + # GIVEN three metrics with different invalid tags + metric_tag_1 = "".join(["x" for _ in range(201)]) # Metric tags must have less than 200 characters + + # WHEN we try to validate those metrics tags + # THEN must be False + with pytest.warns(DatadogDataValidationWarning): + metrics.add_metric(name="metric_2", value=1, tag1=metric_tag_1) From 8caf6831ef4a1b3dc76611bacc7924c39ae149f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 21:30:00 +0100 Subject: [PATCH 76/92] chore(deps-dev): bump xenon from 0.9.0 to 0.9.1 (#2955) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index a00522c4485..89acccbb374 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2898,18 +2898,18 @@ files = [ [[package]] name = "xenon" -version = "0.9.0" +version = "0.9.1" description = "Monitor code metrics for Python on your CI server" optional = false python-versions = "*" files = [ - {file = "xenon-0.9.0-py2.py3-none-any.whl", hash = "sha256:994c80c7f1c6d40596b600b93734d85a5739208f31895ef99f1e4d362caf9e35"}, - {file = "xenon-0.9.0.tar.gz", hash = "sha256:d2b9cb6c6260f771a432c1e588e51fddb17858f88f73ef641e7532f7a5f58fb8"}, + {file = "xenon-0.9.1-py2.py3-none-any.whl", hash = "sha256:b2888a5764ebd57a1f9f1624fde86e8303cb30c686e492f19d98867c458f7870"}, + {file = "xenon-0.9.1.tar.gz", hash = "sha256:d6745111c3e258b749a4fd424b1b899d99ea183cea232365ee2f88fe7d80c03b"}, ] [package.dependencies] PyYAML = ">=4.2b1,<7.0" -radon = ">=4,<6" +radon = ">=4,<7" requests = ">=2.0,<3.0" [[package]] @@ -2949,4 +2949,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "d99019198a55e402af3251eb826136b743dcced7df7faa84c1b920f009dd4dbf" +content-hash = "0d10a97be8e144737d6e0b2b9fafedafde51e709304e3cc21ce5be31afb0b317" diff --git a/pyproject.toml b/pyproject.toml index 04998e0da56..1fb310ff78a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ pdoc3 = "^0.10.0" pytest-asyncio = "^0.21.1" bandit = "^1.7.5" radon = "^5.1.0" -xenon = "^0.9.0" +xenon = "^0.9.1" mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" pytest-xdist = "^3.3.1" From a4fa8bfe4f9b3029c56b6647ba1af3c5dd32519e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 22:38:45 +0100 Subject: [PATCH 77/92] chore(deps): bump actions/setup-node from 3.7.0 to 3.8.0 (#2957) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish_v2_layer.yml | 2 +- .github/workflows/reusable_deploy_v2_layer_stack.yml | 2 +- .github/workflows/reusable_deploy_v2_sar.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index 1b5c668d79d..eb6151c9b95 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -101,7 +101,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - name: Setup Node.js - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 with: node-version: "16.12" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index ef06b82518e..fca8cb13fa6 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -156,7 +156,7 @@ jobs: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} - name: Setup Node.js - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 with: node-version: "16.12" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v2_sar.yml b/.github/workflows/reusable_deploy_v2_sar.yml index beab36f24c2..ee84d55ed45 100644 --- a/.github/workflows/reusable_deploy_v2_sar.yml +++ b/.github/workflows/reusable_deploy_v2_sar.yml @@ -111,7 +111,7 @@ jobs: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_SAR_V2_ROLE_ARN }} - name: Setup Node.js - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 with: node-version: ${{ env.NODE_VERSION }} - name: Download artifact diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 94e5f02e5c7..3285c375cd0 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -61,7 +61,7 @@ jobs: architecture: "x64" cache: "poetry" - name: Setup Node.js - uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0 + uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 with: node-version: "16.12" - name: Install CDK CLI From dbd80cfdb76a3de7d4d74454a6f9c6fedc32721e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 07:52:58 +0100 Subject: [PATCH 78/92] chore(deps-dev): bump cfn-lint from 0.79.6 to 0.79.7 (#2956) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 89acccbb374..ec0cfe06336 100644 --- a/poetry.lock +++ b/poetry.lock @@ -390,13 +390,13 @@ files = [ [[package]] name = "cfn-lint" -version = "0.79.6" +version = "0.79.7" description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved" optional = false python-versions = ">=3.7, <=4.0, !=4.0" files = [ - {file = "cfn-lint-0.79.6.tar.gz", hash = "sha256:09fc9cc497fc6d15e8b822a98fa0628ed6f8e9bcce6c289d95b2fc71d50aa63f"}, - {file = "cfn_lint-0.79.6-py3-none-any.whl", hash = "sha256:b67154460acb466e837590caa7a76bd95ec908961f21ba6de2d985309668ea29"}, + {file = "cfn-lint-0.79.7.tar.gz", hash = "sha256:fcdc195a89810482af93a335b57500fc928111998d8389087f85fd59155fc904"}, + {file = "cfn_lint-0.79.7-py3-none-any.whl", hash = "sha256:05d819e47f74f4d4862b874b0cc911b4ff9773862601ffec8a4f8791df0eab3a"}, ] [package.dependencies] @@ -2949,4 +2949,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "0d10a97be8e144737d6e0b2b9fafedafde51e709304e3cc21ce5be31afb0b317" +content-hash = "941c5fad32f86c3c8678bc7106ab34ca08c34ec75683cd54af5f81cb8c2edb20" diff --git a/pyproject.toml b/pyproject.toml index 1fb310ff78a..27725583125 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -88,7 +88,7 @@ aws-sdk = ["boto3"] datadog=["datadog-lambda"] [tool.poetry.group.dev.dependencies] -cfn-lint = "0.79.6" +cfn-lint = "0.79.7" mypy = "^1.1.1" types-python-dateutil = "^2.8.19.6" httpx = ">=0.23.3,<0.25.0" From 0f14e2c7ad509e974d6302dbaa025aeee148627a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 09:01:54 +0200 Subject: [PATCH 79/92] chore(ci): changelog rebuild (#2958) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index caf81f591a6..0bc22aa74fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,55 +25,60 @@ ## Features +* **event_handler:** allow stripping route prefixes using regexes ([#2521](https://github.com/aws-powertools/powertools-lambda-python/issues/2521)) * **layers:** add new comercial region Israel(Tel Aviv) ([#2907](https://github.com/aws-powertools/powertools-lambda-python/issues/2907)) +* **metrics:** add Datadog observability provider ([#2906](https://github.com/aws-powertools/powertools-lambda-python/issues/2906)) * **metrics:** support to bring your own metrics provider ([#2194](https://github.com/aws-powertools/powertools-lambda-python/issues/2194)) ## Maintenance * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) -* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) -* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) * **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) -* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) +* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) * **deps:** bump gitpython from 3.1.31 to 3.1.32 in /docs ([#2948](https://github.com/aws-powertools/powertools-lambda-python/issues/2948)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) * **deps:** bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 ([#2946](https://github.com/aws-powertools/powertools-lambda-python/issues/2946)) -* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) +* **deps:** bump actions/setup-node from 3.7.0 to 3.8.0 ([#2957](https://github.com/aws-powertools/powertools-lambda-python/issues/2957)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) +* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump cfn-lint from 0.79.6 to 0.79.7 ([#2956](https://github.com/aws-powertools/powertools-lambda-python/issues/2956)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) * **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) +* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) -* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) * **deps-dev:** bump aws-cdk from 2.90.0 to 2.91.0 ([#2947](https://github.com/aws-powertools/powertools-lambda-python/issues/2947)) -* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) +* **deps-dev:** bump xenon from 0.9.0 to 0.9.1 ([#2955](https://github.com/aws-powertools/powertools-lambda-python/issues/2955)) +* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From 5bd446b07d28bf6882f8dbbfa5a943266775ee9a Mon Sep 17 00:00:00 2001 From: aal80 Date: Tue, 15 Aug 2023 02:51:20 -0500 Subject: [PATCH 80/92] docs(metrics): update Datadog integration diagram (#2954) Co-authored-by: Leandro Damascena --- docs/core/metrics/datadog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/core/metrics/datadog.md b/docs/core/metrics/datadog.md index fb5927b3a63..eb036fd3270 100644 --- a/docs/core/metrics/datadog.md +++ b/docs/core/metrics/datadog.md @@ -20,9 +20,10 @@ stateDiagram-v2 LambdaFn --> LambdaCode LambdaCode --> DatadogSDK DatadogSDK --> DatadogExtension + DatadogExtension --> Datadog: async state LambdaExtension { - DatadogExtension --> Datadog: async + DatadogExtension } ``` From bfde1c9124910851f3de41b1db54e48e2bba7f16 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Tue, 15 Aug 2023 11:07:00 +0200 Subject: [PATCH 81/92] docs(roadmap): add GovCloud and China region item (#2960) --- docs/roadmap.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index fc8b4441754..c2de6829fb4 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -95,7 +95,7 @@ Since JWT is a close second, this new utility would cover higher level functions We want to make this easier by extending certain utilities to accept a `metrics` instance and metrics configuration (what metrics to create). It would be opt-in due to costs associated with creating metrics. -!!! question "Got ideas for custom metrics? Open up a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE)"{target="_blank"} +!!! question "Got ideas for custom metrics? Open up a [feature request](https://github.com/aws-powertools/powertools-lambda-python/issues/new?assignees=&labels=feature-request%2Ctriage&projects=&template=feature_request.yml&title=Feature+request%3A+TITLE)" **Major updates** @@ -104,6 +104,19 @@ We want to make this easier by extending certain utilities to accept a `metrics` - [ ] RFC to outline metrics for Event Handler (_e.g., validation errors_ ) - [ ] RFC to outline metrics for Idempotency (_e.g., cache hit_) +### Lambda Layer in GovCloud and China region + +We want to investigate security and scaling requirements for these special regions, so they're in sync for every release. + +!!! note "Help us prioritize it by reaching out to your AWS representatives or [via email](mailto:aws-lambda-powertools-feedback@amazon.com)." + +**Major updates** + +- [ ] Gather agencies and customers name to prioritize it +- [ ] Investigate security requirements for special regions +- [ ] Update CDK Layer construct to include regions +- [ ] Create additional infrastructure for special regions + ### V3 With Python 3.7 reaching [end-of-life in AWS Lambda by the end of the year](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html), we want to plan some breaking changes. As always, we plan on having ample notice, a detailed upgrade guide, and keep breaking changes to a minimum to ease transition (e.g., it took ~7 months from v2 to surpass v1 downloads). From 181fc33af9ffc323cdecddb859db8add5874b634 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 15 Aug 2023 17:46:57 +0100 Subject: [PATCH 82/92] fix(parser): API Gateway V2 request context scope field should be optional (#2961) --- aws_lambda_powertools/utilities/parser/models/apigwv2.py | 2 +- tests/unit/parser/test_apigwv2.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/parser/models/apigwv2.py b/aws_lambda_powertools/utilities/parser/models/apigwv2.py index 3be793dd951..8f0f8dbf50c 100644 --- a/aws_lambda_powertools/utilities/parser/models/apigwv2.py +++ b/aws_lambda_powertools/utilities/parser/models/apigwv2.py @@ -25,7 +25,7 @@ class RequestContextV2AuthorizerIam(BaseModel): class RequestContextV2AuthorizerJwt(BaseModel): claims: Dict[str, Any] - scopes: List[str] + scopes: Optional[List[str]] = None class RequestContextV2Authorizer(BaseModel): diff --git a/tests/unit/parser/test_apigwv2.py b/tests/unit/parser/test_apigwv2.py index 9ffc7f525bc..b52bad28b40 100644 --- a/tests/unit/parser/test_apigwv2.py +++ b/tests/unit/parser/test_apigwv2.py @@ -63,6 +63,13 @@ def test_apigw_v2_event_jwt_authorizer(): assert parsed_event.stageVariables == raw_event["stageVariables"] +def test_apigw_v2_event_empty_jwt_scopes(): + raw_event = load_event("apiGatewayProxyV2Event.json") + raw_event["requestContext"]["authorizer"]["jwt"]["scopes"] = None + + APIGatewayProxyEventV2Model(**raw_event) + + def test_api_gateway_proxy_v2_event_lambda_authorizer(): raw_event = load_event("apiGatewayProxyV2LambdaAuthorizerEvent.json") parsed_event: APIGatewayProxyEventV2Model = APIGatewayProxyEventV2Model(**raw_event) From 203b478bce53112ae28eab4bee65babc494e458b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 22:04:30 +0100 Subject: [PATCH 83/92] chore(deps): bump actions/dependency-review-action from 3.0.7 to 3.0.8 (#2963) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 3052aec7dbc..072a9ae47c4 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -19,4 +19,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: 'Dependency Review' - uses: actions/dependency-review-action@7d90b4f05fea31dde1c4a1fb3fa787e197ea93ab # v3.0.7 + uses: actions/dependency-review-action@f6fff72a3217f580d5afd49a46826795305b63c7 # v3.0.8 From bef8f0878adf8005a7199a32e3b42480c95d3d50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 22:08:07 +0100 Subject: [PATCH 84/92] chore(deps-dev): bump aws-cdk from 2.91.0 to 2.92.0 (#2965) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index a293273d144..755bd95890c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,13 +11,13 @@ "package-lock.json": "^1.0.0" }, "devDependencies": { - "aws-cdk": "^2.91.0" + "aws-cdk": "^2.92.0" } }, "node_modules/aws-cdk": { - "version": "2.91.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.91.0.tgz", - "integrity": "sha512-YSnTiLyNtng0eW1y9XdyopSTP3Kuyhs5cF5iRcaCk9o+3zrvadgxvcWVT7caXNfE8iOI9IKwSd2GiABeVd20eQ==", + "version": "2.92.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.92.0.tgz", + "integrity": "sha512-9aAWJvZWSBJQxcsDopXYUAm6/pGz6vOQy2zfkn+YBuBkNelvW+ok15KPY4xn5m76tYnN79W03Gnfp/nxZUlcww==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -51,9 +51,9 @@ }, "dependencies": { "aws-cdk": { - "version": "2.91.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.91.0.tgz", - "integrity": "sha512-YSnTiLyNtng0eW1y9XdyopSTP3Kuyhs5cF5iRcaCk9o+3zrvadgxvcWVT7caXNfE8iOI9IKwSd2GiABeVd20eQ==", + "version": "2.92.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.92.0.tgz", + "integrity": "sha512-9aAWJvZWSBJQxcsDopXYUAm6/pGz6vOQy2zfkn+YBuBkNelvW+ok15KPY4xn5m76tYnN79W03Gnfp/nxZUlcww==", "dev": true, "requires": { "fsevents": "2.3.2" diff --git a/package.json b/package.json index 485a25885b2..a08922eb2bb 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "aws-lambda-powertools-python-e2e", "version": "1.0.0", "devDependencies": { - "aws-cdk": "^2.91.0" + "aws-cdk": "^2.92.0" }, "dependencies": { "package-lock.json": "^1.0.0" From a606bdecbc2c5a0fa696f9abe219a49be6aa5bf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 23:07:44 +0100 Subject: [PATCH 85/92] chore(deps-dev): bump radon from 5.1.0 to 6.0.1 (#2964) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- poetry.lock | 24 ++++++++---------------- pyproject.toml | 2 +- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/poetry.lock b/poetry.lock index ec0cfe06336..74b2ead3108 100644 --- a/poetry.lock +++ b/poetry.lock @@ -870,16 +870,6 @@ files = [ docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] -[[package]] -name = "future" -version = "0.18.3" -description = "Clean single-source support for Python 3 and 2" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, -] - [[package]] name = "ghp-import" version = "2.1.0" @@ -2294,19 +2284,21 @@ pyyaml = "*" [[package]] name = "radon" -version = "5.1.0" +version = "6.0.1" description = "Code Metrics in Python" optional = false python-versions = "*" files = [ - {file = "radon-5.1.0-py2.py3-none-any.whl", hash = "sha256:fa74e018197f1fcb54578af0f675d8b8e2342bd8e0b72bef8197bc4c9e645f36"}, - {file = "radon-5.1.0.tar.gz", hash = "sha256:cb1d8752e5f862fb9e20d82b5f758cbc4fb1237c92c9a66450ea0ea7bf29aeee"}, + {file = "radon-6.0.1-py2.py3-none-any.whl", hash = "sha256:632cc032364a6f8bb1010a2f6a12d0f14bc7e5ede76585ef29dc0cecf4cd8859"}, + {file = "radon-6.0.1.tar.gz", hash = "sha256:d1ac0053943a893878940fedc8b19ace70386fc9c9bf0a09229a44125ebf45b5"}, ] [package.dependencies] colorama = {version = ">=0.4.1", markers = "python_version > \"3.4\""} -future = "*" -mando = ">=0.6,<0.7" +mando = ">=0.6,<0.8" + +[package.extras] +toml = ["tomli (>=2.0.1)"] [[package]] name = "regex" @@ -2949,4 +2941,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "941c5fad32f86c3c8678bc7106ab34ca08c34ec75683cd54af5f81cb8c2edb20" +content-hash = "57137624bcbcdc3e936c90c912771020755f8af413a3e5265d53a74ef066872a" diff --git a/pyproject.toml b/pyproject.toml index 27725583125..0be57f1826d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ pytest-mock = "^3.11.1" pdoc3 = "^0.10.0" pytest-asyncio = "^0.21.1" bandit = "^1.7.5" -radon = "^5.1.0" +radon = "^6.0.1" xenon = "^0.9.1" mkdocs-git-revision-date-plugin = "^0.3.2" mike = "^1.1.2" From 4918b444677321569b35ea7a884993f512fe193f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 16 Aug 2023 09:00:50 +0100 Subject: [PATCH 86/92] chore(ci): changelog rebuild (#2966) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc22aa74fe..f5bcad4a3d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * **logger:** strip xray_trace_id when explicitly disabled ([#2852](https://github.com/aws-powertools/powertools-lambda-python/issues/2852)) * **metrics:** proxy service and namespace attrs to provider ([#2910](https://github.com/aws-powertools/powertools-lambda-python/issues/2910)) +* **parser:** API Gateway V2 request context scope field should be optional ([#2961](https://github.com/aws-powertools/powertools-lambda-python/issues/2961)) ## Code Refactoring @@ -16,11 +17,13 @@ ## Documentation -* **batch:** explain record type discrepancy in failure and success handler ([#2868](https://github.com/aws-powertools/powertools-lambda-python/issues/2868)) * **batch:** new visuals and error handling section ([#2857](https://github.com/aws-powertools/powertools-lambda-python/issues/2857)) +* **batch:** explain record type discrepancy in failure and success handler ([#2868](https://github.com/aws-powertools/powertools-lambda-python/issues/2868)) +* **metrics:** update Datadog integration diagram ([#2954](https://github.com/aws-powertools/powertools-lambda-python/issues/2954)) * **navigation:** remove nofollow attribute for internal links ([#2867](https://github.com/aws-powertools/powertools-lambda-python/issues/2867)) * **navigation:** add nofollow attribute ([#2842](https://github.com/aws-powertools/powertools-lambda-python/issues/2842)) * **roadmap:** update roadmap themes ([#2915](https://github.com/aws-powertools/powertools-lambda-python/issues/2915)) +* **roadmap:** add GovCloud and China region item ([#2960](https://github.com/aws-powertools/powertools-lambda-python/issues/2960)) * **tutorial:** add support for Python 3.11 ([#2860](https://github.com/aws-powertools/powertools-lambda-python/issues/2860)) ## Features @@ -34,51 +37,54 @@ * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) * **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump gitpython from 3.1.31 to 3.1.32 in /docs ([#2948](https://github.com/aws-powertools/powertools-lambda-python/issues/2948)) * **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 ([#2946](https://github.com/aws-powertools/powertools-lambda-python/issues/2946)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) -* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) +* **deps:** bump actions/setup-node from 3.7.0 to 3.8.0 ([#2957](https://github.com/aws-powertools/powertools-lambda-python/issues/2957)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump gitpython from 3.1.31 to 3.1.32 in /docs ([#2948](https://github.com/aws-powertools/powertools-lambda-python/issues/2948)) -* **deps:** bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 ([#2946](https://github.com/aws-powertools/powertools-lambda-python/issues/2946)) +* **deps:** bump actions/dependency-review-action from 3.0.7 to 3.0.8 ([#2963](https://github.com/aws-powertools/powertools-lambda-python/issues/2963)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) -* **deps:** bump actions/setup-node from 3.7.0 to 3.8.0 ([#2957](https://github.com/aws-powertools/powertools-lambda-python/issues/2957)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) +* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) -* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) -* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) -* **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) +* **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) * **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) * **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) +* **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) +* **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) * **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) -* **deps-dev:** bump cfn-lint from 0.79.6 to 0.79.7 ([#2956](https://github.com/aws-powertools/powertools-lambda-python/issues/2956)) +* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) -* **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) -* **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) -* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) -* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) * **deps-dev:** bump aws-cdk from 2.90.0 to 2.91.0 ([#2947](https://github.com/aws-powertools/powertools-lambda-python/issues/2947)) * **deps-dev:** bump xenon from 0.9.0 to 0.9.1 ([#2955](https://github.com/aws-powertools/powertools-lambda-python/issues/2955)) -* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) +* **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) +* **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump cfn-lint from 0.79.6 to 0.79.7 ([#2956](https://github.com/aws-powertools/powertools-lambda-python/issues/2956)) +* **deps-dev:** bump aws-cdk from 2.91.0 to 2.92.0 ([#2965](https://github.com/aws-powertools/powertools-lambda-python/issues/2965)) +* **deps-dev:** bump radon from 5.1.0 to 6.0.1 ([#2964](https://github.com/aws-powertools/powertools-lambda-python/issues/2964)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From 2c39bb85041f95e98ba3d99004381c177de5c81e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 00:18:01 +0100 Subject: [PATCH 87/92] chore(deps-dev): bump the boto-typing group with 3 updates (#2967) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 26 +++++++++++++------------- pyproject.toml | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index 74b2ead3108..d225f187002 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1668,13 +1668,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-cloudwatch" -version = "1.28.16" -description = "Type annotations for boto3.CloudWatch 1.28.16 service generated with mypy-boto3-builder 7.17.1" +version = "1.28.28" +description = "Type annotations for boto3.CloudWatch 1.28.28 service generated with mypy-boto3-builder 7.17.3" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-cloudwatch-1.28.16.tar.gz", hash = "sha256:15ccb83964bae8c15479852a9526898e6105defd6d09cc326034e98e4b00a896"}, - {file = "mypy_boto3_cloudwatch-1.28.16-py3-none-any.whl", hash = "sha256:fc3c5df0e67ac4b4bf246bcb06ab2ecb9ccff6a5fa1ced51dd2fd8e59a2863df"}, + {file = "mypy-boto3-cloudwatch-1.28.28.tar.gz", hash = "sha256:6dfad8f0f5fffbe1350c6e0f2fab4a0e184d1714f3de644937ad0bc458e7229c"}, + {file = "mypy_boto3_cloudwatch-1.28.28-py3-none-any.whl", hash = "sha256:102a5f5c63ec2654f6446e6ae12705de4bebc1a599fe35608e953ce151cc29a9"}, ] [package.dependencies] @@ -1682,13 +1682,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-dynamodb" -version = "1.28.19" -description = "Type annotations for boto3.DynamoDB 1.28.19 service generated with mypy-boto3-builder 7.17.2" +version = "1.28.27" +description = "Type annotations for boto3.DynamoDB 1.28.27 service generated with mypy-boto3-builder 7.17.3" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-dynamodb-1.28.19.tar.gz", hash = "sha256:6b9b407c9e2fc73ac5d475a8c98af4e1bea3899e5e74ce00d11cb9c878af761b"}, - {file = "mypy_boto3_dynamodb-1.28.19-py3-none-any.whl", hash = "sha256:a0859c469f46f7e354ae707f1f97bea36746d5538ee851b18d5b61cfb9cf91b9"}, + {file = "mypy-boto3-dynamodb-1.28.27.tar.gz", hash = "sha256:b6786cf953e65293ec25c791e7efcd8ededceb6bda2e04910785b0f62584417d"}, + {file = "mypy_boto3_dynamodb-1.28.27-py3-none-any.whl", hash = "sha256:218f7bcb04010058aea5a735d52b87c4f70e8c5feb44e64ab6baf377ebb4e22a"}, ] [package.dependencies] @@ -1724,13 +1724,13 @@ typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""} [[package]] name = "mypy-boto3-s3" -version = "1.28.19" -description = "Type annotations for boto3.S3 1.28.19 service generated with mypy-boto3-builder 7.17.2" +version = "1.28.27" +description = "Type annotations for boto3.S3 1.28.27 service generated with mypy-boto3-builder 7.17.3" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-boto3-s3-1.28.19.tar.gz", hash = "sha256:b8104b191924d8672068d21d748c0f8ae0b0e1950324cb315ec8a1ceed9d23ac"}, - {file = "mypy_boto3_s3-1.28.19-py3-none-any.whl", hash = "sha256:d3759a8fb004f482565904d788d844eeccf3e03b8fa1b96a0f82ba1527ef4022"}, + {file = "mypy-boto3-s3-1.28.27.tar.gz", hash = "sha256:f1094344f68d1ffe2b998404e2e4ff9aa4239438692187fa83ad7b734739991c"}, + {file = "mypy_boto3_s3-1.28.27-py3-none-any.whl", hash = "sha256:f4fdefbfe084c92a6b3d000689e61ab12a985a72b07c5ff157f8a66bcbdb83ba"}, ] [package.dependencies] @@ -2941,4 +2941,4 @@ validation = ["fastjsonschema"] [metadata] lock-version = "2.0" python-versions = "^3.7.4" -content-hash = "57137624bcbcdc3e936c90c912771020755f8af413a3e5265d53a74ef066872a" +content-hash = "58807838331ba630a2669d8ea9dd3e745fb86f6de03b340dec16a494dc984c46" diff --git a/pyproject.toml b/pyproject.toml index 0be57f1826d..945aa6a2cc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,13 +58,13 @@ aws-cdk-lib = "^2.88.0" pytest-benchmark = "^4.0.0" mypy-boto3-appconfig = "^1.28.16" mypy-boto3-cloudformation = "^1.28.19" -mypy-boto3-cloudwatch = "^1.28.16" -mypy-boto3-dynamodb = "^1.28.19" +mypy-boto3-cloudwatch = "^1.28.28" +mypy-boto3-dynamodb = "^1.28.27" mypy-boto3-lambda = "^1.28.19" mypy-boto3-logs = "^1.28.16" mypy-boto3-secretsmanager = "^1.28.24" mypy-boto3-ssm = "^1.28.16" -mypy-boto3-s3 = "^1.28.19" +mypy-boto3-s3 = "^1.28.27" mypy-boto3-xray = "^1.28.16" types-requests = "^2.31.0" typing-extensions = "^4.6.2" From ac4fe43eab9201a70ba581bdafe8850ef7b6fdbd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 09:59:32 +0100 Subject: [PATCH 88/92] chore(ci): changelog rebuild (#2968) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5bcad4a3d2..04596ef39fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,34 +35,35 @@ ## Maintenance -* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) +* **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) -* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) * **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) * **deps:** bump gitpython from 3.1.31 to 3.1.32 in /docs ([#2948](https://github.com/aws-powertools/powertools-lambda-python/issues/2948)) -* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) * **deps:** bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 ([#2946](https://github.com/aws-powertools/powertools-lambda-python/issues/2946)) -* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump actions/setup-node from 3.7.0 to 3.8.0 ([#2957](https://github.com/aws-powertools/powertools-lambda-python/issues/2957)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump actions/dependency-review-action from 3.0.7 to 3.0.8 ([#2963](https://github.com/aws-powertools/powertools-lambda-python/issues/2963)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) +* **deps:** bump actions/dependency-review-action from 3.0.7 to 3.0.8 ([#2963](https://github.com/aws-powertools/powertools-lambda-python/issues/2963)) +* **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) +* **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) +* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) * **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) -* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) +* **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump radon from 5.1.0 to 6.0.1 ([#2964](https://github.com/aws-powertools/powertools-lambda-python/issues/2964)) * **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) -* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) +* **deps-dev:** bump aws-cdk from 2.91.0 to 2.92.0 ([#2965](https://github.com/aws-powertools/powertools-lambda-python/issues/2965)) * **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) @@ -70,23 +71,23 @@ * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) * **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) -* **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) +* **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) * **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) -* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) +* **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) * **deps-dev:** bump mypy-boto3-appconfig from 1.28.0 to 1.28.12 ([#2861](https://github.com/aws-powertools/powertools-lambda-python/issues/2861)) * **deps-dev:** bump mypy-boto3-ssm from 1.28.0 to 1.28.12 ([#2863](https://github.com/aws-powertools/powertools-lambda-python/issues/2863)) +* **deps-dev:** bump the boto-typing group with 1 update ([#2944](https://github.com/aws-powertools/powertools-lambda-python/issues/2944)) * **deps-dev:** bump aws-cdk from 2.90.0 to 2.91.0 ([#2947](https://github.com/aws-powertools/powertools-lambda-python/issues/2947)) -* **deps-dev:** bump xenon from 0.9.0 to 0.9.1 ([#2955](https://github.com/aws-powertools/powertools-lambda-python/issues/2955)) * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) +* **deps-dev:** bump xenon from 0.9.0 to 0.9.1 ([#2955](https://github.com/aws-powertools/powertools-lambda-python/issues/2955)) * **deps-dev:** bump cfn-lint from 0.79.6 to 0.79.7 ([#2956](https://github.com/aws-powertools/powertools-lambda-python/issues/2956)) -* **deps-dev:** bump aws-cdk from 2.91.0 to 2.92.0 ([#2965](https://github.com/aws-powertools/powertools-lambda-python/issues/2965)) -* **deps-dev:** bump radon from 5.1.0 to 6.0.1 ([#2964](https://github.com/aws-powertools/powertools-lambda-python/issues/2964)) -* **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) +* **deps-dev:** bump the boto-typing group with 3 updates ([#2967](https://github.com/aws-powertools/powertools-lambda-python/issues/2967)) * **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) +* **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From 905aeae11f9219f994699dc99556668c25408346 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 22:05:56 +0100 Subject: [PATCH 89/92] chore(deps): bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates (#2971) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- layer/scripts/layer-balancer/go.mod | 24 +++++++-------- layer/scripts/layer-balancer/go.sum | 48 ++++++++++++++--------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/layer/scripts/layer-balancer/go.mod b/layer/scripts/layer-balancer/go.mod index 5a6f45392eb..cfb05ca1bfd 100644 --- a/layer/scripts/layer-balancer/go.mod +++ b/layer/scripts/layer-balancer/go.mod @@ -3,24 +3,24 @@ module layerbalancer go 1.18 require ( - github.com/aws/aws-sdk-go-v2 v1.20.1 - github.com/aws/aws-sdk-go-v2/config v1.18.33 - github.com/aws/aws-sdk-go-v2/service/lambda v1.39.2 + github.com/aws/aws-sdk-go-v2 v1.20.2 + github.com/aws/aws-sdk-go-v2/config v1.18.34 + github.com/aws/aws-sdk-go-v2/service/lambda v1.39.3 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/sync v0.3.0 ) require ( github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.32 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.21.2 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.33 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.39 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.33 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.40 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.33 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.13.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.21.3 // indirect github.com/aws/smithy-go v1.14.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/layer/scripts/layer-balancer/go.sum b/layer/scripts/layer-balancer/go.sum index 9b7f76ab4d1..e2db967f5a8 100644 --- a/layer/scripts/layer-balancer/go.sum +++ b/layer/scripts/layer-balancer/go.sum @@ -1,29 +1,29 @@ -github.com/aws/aws-sdk-go-v2 v1.20.1 h1:rZBf5DWr7YGrnlTK4kgDQGn1ltqOg5orCYb/UhOFZkg= -github.com/aws/aws-sdk-go-v2 v1.20.1/go.mod h1:NU06lETsFm8fUC6ZjhgDpVBcGZTFQ6XM+LZWZxMI4ac= +github.com/aws/aws-sdk-go-v2 v1.20.2 h1:0Aok9u/HVTk7RtY6M1KDcthbaMKGhhS0eLPxIdSIzRI= +github.com/aws/aws-sdk-go-v2 v1.20.2/go.mod h1:NU06lETsFm8fUC6ZjhgDpVBcGZTFQ6XM+LZWZxMI4ac= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 h1:lN6L3LrYHeZ6xCxaIYtoWCx4GMLk4nRknsh29OMSqHY= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12/go.mod h1:TDCkEAkMTXxTs0oLBGBKpBZbk3NLh8EvAfF0Q3x8/0c= -github.com/aws/aws-sdk-go-v2/config v1.18.33 h1:JKcw5SFxFW/rpM4mOPjv0VQ11E2kxW13F3exWOy7VZU= -github.com/aws/aws-sdk-go-v2/config v1.18.33/go.mod h1:hXO/l9pgY3K5oZJldamP0pbZHdPqqk+4/maa7DSD3cA= -github.com/aws/aws-sdk-go-v2/credentials v1.13.32 h1:lIH1eKPcCY1ylR4B6PkBGRWMHO3aVenOKJHWiS4/G2w= -github.com/aws/aws-sdk-go-v2/credentials v1.13.32/go.mod h1:lL8U3v/Y79YRG69WlAho0OHIKUXCyFvSXaIvfo81sls= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8 h1:DK/9C+UN/X+1+Wm8pqaDksQr2tSLzq+8X1/rI/ZxKEQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8/go.mod h1:ce7BgLQfYr5hQFdy67oX2svto3ufGtm6oBvmsHScI1Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 h1:c8ed/T9T2K5I+h/JzmF5tpI46+OODQ74dzmdo+QnaMg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38/go.mod h1:qggunOChCMu9ZF/UkAfhTz25+U2rLVb3ya0Ua6TTfCA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 h1:hNeAAymUY5gu11WrrmFb3CVIp9Dar9hbo44yzzcQpzA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32/go.mod h1:0ZXSqrty4FtQ7p8TEuRde/SZm9X05KT18LAUlR40Ln0= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39 h1:fc0ukRAiP1syoSGZYu+DaE+FulSYhTiJ8WpVu5jElU4= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39/go.mod h1:WLAW8PT7+JhjZfLSWe7WEJaJu0GNo0cKc2Zyo003RBs= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 h1:dGAseBFEYxth10V23b5e2mAS+tX7oVbfYHD6dnDdAsg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32/go.mod h1:4jwAWKEkCR0anWk5+1RbfSg1R5Gzld7NLiuaq5bTR/Y= -github.com/aws/aws-sdk-go-v2/service/lambda v1.39.2 h1:LMKc3k1+bvr4xUEPrw11U/fZpJDoCZut7b+QC8OuDtY= -github.com/aws/aws-sdk-go-v2/service/lambda v1.39.2/go.mod h1:gDCQ1weogYZfHYZIVppDYgGS57zQALJiDL+9yGAts58= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 h1:A2RlEMo4SJSwbNoUUgkxTAEMduAy/8wG3eB2b2lP4gY= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.2/go.mod h1:ju+nNXUunfIFamXUIZQiICjnO/TPlOmWcYhZcSy7xaE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 h1:OJELEgyaT2kmaBGZ+myyZbTTLobfe3ox3FSh5eYK9Qs= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2/go.mod h1:ubDBBaDFs1GHijSOTi8ljppML15GLG0HxhILtbjNNYQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.2 h1:ympg1+Lnq33XLhcK/xTG4yZHPs1Oyxu+6DEWbl7qOzA= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.2/go.mod h1:FQ/DQcOfESELfJi5ED+IPPAjI5xC6nxtSolVVB773jM= +github.com/aws/aws-sdk-go-v2/config v1.18.34 h1:bFf7CtSgwz/vE4tl0cNbWbf6EDQ2TZR5VrsrO9ardoY= +github.com/aws/aws-sdk-go-v2/config v1.18.34/go.mod h1:uJ/keVhwR8vsSaErMu2Vb3dArUZZKLVTcOsKXIFfvjs= +github.com/aws/aws-sdk-go-v2/credentials v1.13.33 h1:esA1X5Eti1xSGCF0W0LYpHH/r6p+MqT0DiKXsfDEPxs= +github.com/aws/aws-sdk-go-v2/credentials v1.13.33/go.mod h1:jNC10ZEYuLlt9IOowix60yNiO6vGA14RVK3oUfX5KgI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.9 h1:DnNHcClgyFV5suHJ4axqhmG3YeRGgIu6yv29IEWR9aE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.9/go.mod h1:kz0hzQXlc/5Y5mkbwTKX8A+aTRA45t8Aavly60bQzAQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.39 h1:OBokd2jreL7ItwqRRcN5QiSt24/i2r742aRsd2qMyeg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.39/go.mod h1:OLmjwglQh90dCcFJDGD+T44G0ToLH+696kRwRhS1KOU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.33 h1:gcRN6PXAo8w3HYFp2wFyr+WYEP4n/a25/IOhzJl36Yw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.33/go.mod h1:S/zgOphghZAIvrbtvsVycoOncfqh1Hc4uGDIHqDLwTU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.40 h1:glWaI8WyeYqQN4zh4zqogzSpNPj8rf11Nj+oE3ghQPw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.40/go.mod h1:OCnFHzgaBY2PuGiHSzLlfqV4j5rJrky7YMfBXcx2Uk0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.33 h1:cr70Hw6Lq9cqRst1y4YOHLiaVWaWtBPiqdloinNkfis= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.33/go.mod h1:kcNtzCcEoflp+6e2CDTmm2h3xQGZOBZqYA/8DhYx/S8= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.3 h1:8T6YpLdpu7wqPr9RZALRJWEm+NbkQykzN6Mdy2lOIQw= +github.com/aws/aws-sdk-go-v2/service/lambda v1.39.3/go.mod h1:PxfJo3p3ze0lFI8Zsu0tqjB2edJu2ZAEzQzT2LQUY3o= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.3 h1:nceOkYE0jmaG9CoyXHJJm00FAQ8JE+/LCKJJ06hH/Nc= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.3/go.mod h1:DApEBnZzexe+LDLaNrGOJA8xtRMCpikLW1gX7jZhHxc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.3 h1:90qW9puxI7LgmiYKSPhx6wz4XqgVauTxCyS3185+JpA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.3/go.mod h1:kKpyLjToIS7E3z0672lBhxIPD+uoQ9V0MYRYCVGIkO0= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.3 h1:s3wBkMxfA/u2EJJl6KRsPcWv858lDHkhinqXyN6fkZI= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.3/go.mod h1:b+y9zL57mwCRy6ftp9Nc7CONGHX3sZ50ZCLTrI5xpCc= github.com/aws/smithy-go v1.14.1 h1:EFKMUmH/iHMqLiwoEDx2rRjRQpI1YCn5jTysoaDujFs= github.com/aws/smithy-go v1.14.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= From ebe5c47bb6b14fc44e2ce1d7009007a3d48e5cf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 22:07:25 +0100 Subject: [PATCH 90/92] chore(deps): bump actions/setup-node from 3.8.0 to 3.8.1 (#2970) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena --- .github/workflows/publish_v2_layer.yml | 2 +- .github/workflows/reusable_deploy_v2_layer_stack.yml | 2 +- .github/workflows/reusable_deploy_v2_sar.yml | 2 +- .github/workflows/run-e2e-tests.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish_v2_layer.yml b/.github/workflows/publish_v2_layer.yml index eb6151c9b95..d62bd12cead 100644 --- a/.github/workflows/publish_v2_layer.yml +++ b/.github/workflows/publish_v2_layer.yml @@ -101,7 +101,7 @@ jobs: - name: Install poetry run: pipx install git+https://github.com/python-poetry/poetry@68b88e5390720a3dd84f02940ec5200bfce39ac6 # v1.5.0 - name: Setup Node.js - uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: "16.12" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v2_layer_stack.yml b/.github/workflows/reusable_deploy_v2_layer_stack.yml index fca8cb13fa6..1f7f0818f22 100644 --- a/.github/workflows/reusable_deploy_v2_layer_stack.yml +++ b/.github/workflows/reusable_deploy_v2_layer_stack.yml @@ -156,7 +156,7 @@ jobs: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.AWS_LAYERS_ROLE_ARN }} - name: Setup Node.js - uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: "16.12" - name: Setup python diff --git a/.github/workflows/reusable_deploy_v2_sar.yml b/.github/workflows/reusable_deploy_v2_sar.yml index ee84d55ed45..a381d8832c2 100644 --- a/.github/workflows/reusable_deploy_v2_sar.yml +++ b/.github/workflows/reusable_deploy_v2_sar.yml @@ -111,7 +111,7 @@ jobs: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_SAR_V2_ROLE_ARN }} - name: Setup Node.js - uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: ${{ env.NODE_VERSION }} - name: Download artifact diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 3285c375cd0..d3531db71f3 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -61,7 +61,7 @@ jobs: architecture: "x64" cache: "poetry" - name: Setup Node.js - uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: "16.12" - name: Install CDK CLI From c4afbbfc0a217f9a04305273d40ea790e5ac65ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Aug 2023 14:07:15 +0200 Subject: [PATCH 91/92] chore(ci): changelog rebuild (#2972) Co-authored-by: Powertools for AWS Lambda (Python) bot --- CHANGELOG.md | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04596ef39fb..efc7033629d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,43 +37,45 @@ * **ci:** enable protected branch auditing ([#2913](https://github.com/aws-powertools/powertools-lambda-python/issues/2913)) * **ci:** group dependabot updates ([#2896](https://github.com/aws-powertools/powertools-lambda-python/issues/2896)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) -* **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) -* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) +* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) * **deps:** bump gitpython from 3.1.31 to 3.1.32 in /docs ([#2948](https://github.com/aws-powertools/powertools-lambda-python/issues/2948)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.0 to 1.38.1 in /layer/scripts/layer-balancer ([#2876](https://github.com/aws-powertools/powertools-lambda-python/issues/2876)) +* **deps:** bump actions/dependency-review-action from 3.0.6 to 3.0.7 ([#2941](https://github.com/aws-powertools/powertools-lambda-python/issues/2941)) * **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.29 to 1.18.30 in /layer/scripts/layer-balancer ([#2875](https://github.com/aws-powertools/powertools-lambda-python/issues/2875)) -* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) * **deps:** bump pypa/gh-action-pypi-publish from 1.8.9 to 1.8.10 ([#2946](https://github.com/aws-powertools/powertools-lambda-python/issues/2946)) -* **deps:** bump github.com/aws/aws-sdk-go-v2 from 1.19.0 to 1.19.1 in /layer/scripts/layer-balancer ([#2877](https://github.com/aws-powertools/powertools-lambda-python/issues/2877)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.28 to 1.18.29 in /layer/scripts/layer-balancer ([#2844](https://github.com/aws-powertools/powertools-lambda-python/issues/2844)) * **deps:** bump actions/setup-node from 3.7.0 to 3.8.0 ([#2957](https://github.com/aws-powertools/powertools-lambda-python/issues/2957)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2933](https://github.com/aws-powertools/powertools-lambda-python/issues/2933)) +* **deps:** bump actions/setup-node from 3.8.0 to 3.8.1 ([#2970](https://github.com/aws-powertools/powertools-lambda-python/issues/2970)) +* **deps:** bump actions/dependency-review-action from 3.0.7 to 3.0.8 ([#2963](https://github.com/aws-powertools/powertools-lambda-python/issues/2963)) +* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.37.1 to 1.38.0 in /layer/scripts/layer-balancer ([#2843](https://github.com/aws-powertools/powertools-lambda-python/issues/2843)) * **deps:** bump github.com/aws/aws-sdk-go-v2/service/lambda from 1.38.1 to 1.39.0 in /layer/scripts/layer-balancer ([#2890](https://github.com/aws-powertools/powertools-lambda-python/issues/2890)) -* **deps:** bump actions/dependency-review-action from 3.0.7 to 3.0.8 ([#2963](https://github.com/aws-powertools/powertools-lambda-python/issues/2963)) * **deps:** bump pydantic from 1.10.11 to 1.10.12 ([#2846](https://github.com/aws-powertools/powertools-lambda-python/issues/2846)) +* **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 3 updates ([#2971](https://github.com/aws-powertools/powertools-lambda-python/issues/2971)) * **deps:** bump the layer-balancer group in /layer/scripts/layer-balancer with 2 updates ([#2904](https://github.com/aws-powertools/powertools-lambda-python/issues/2904)) -* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) * **deps:** bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.9 ([#2943](https://github.com/aws-powertools/powertools-lambda-python/issues/2943)) -* **deps:** bump slsa-framework/slsa-github-generator from 1.7.0 to 1.8.0 ([#2927](https://github.com/aws-powertools/powertools-lambda-python/issues/2927)) +* **deps:** bump github.com/aws/aws-sdk-go-v2/config from 1.18.30 to 1.18.31 in /layer/scripts/layer-balancer ([#2889](https://github.com/aws-powertools/powertools-lambda-python/issues/2889)) +* **deps:** bump squidfunk/mkdocs-material from `33e28bd` to `cd3a522` in /docs ([#2859](https://github.com/aws-powertools/powertools-lambda-python/issues/2859)) * **deps-dev:** bump sentry-sdk from 1.28.1 to 1.29.0 ([#2900](https://github.com/aws-powertools/powertools-lambda-python/issues/2900)) * **deps-dev:** bump cfn-lint from 0.79.5 to 0.79.6 ([#2899](https://github.com/aws-powertools/powertools-lambda-python/issues/2899)) * **deps-dev:** bump the boto-typing group with 11 updates ([#2901](https://github.com/aws-powertools/powertools-lambda-python/issues/2901)) -* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) +* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) * **deps-dev:** bump aws-cdk from 2.88.0 to 2.89.0 ([#2887](https://github.com/aws-powertools/powertools-lambda-python/issues/2887)) -* **deps-dev:** bump radon from 5.1.0 to 6.0.1 ([#2964](https://github.com/aws-powertools/powertools-lambda-python/issues/2964)) +* **deps-dev:** bump the boto-typing group with 3 updates ([#2967](https://github.com/aws-powertools/powertools-lambda-python/issues/2967)) * **deps-dev:** bump mkdocs-material from 9.1.19 to 9.1.21 ([#2894](https://github.com/aws-powertools/powertools-lambda-python/issues/2894)) -* **deps-dev:** bump ruff from 0.0.280 to 0.0.281 ([#2891](https://github.com/aws-powertools/powertools-lambda-python/issues/2891)) -* **deps-dev:** bump aws-cdk from 2.91.0 to 2.92.0 ([#2965](https://github.com/aws-powertools/powertools-lambda-python/issues/2965)) +* **deps-dev:** bump radon from 5.1.0 to 6.0.1 ([#2964](https://github.com/aws-powertools/powertools-lambda-python/issues/2964)) * **deps-dev:** bump the boto-typing group with 4 updates ([#2928](https://github.com/aws-powertools/powertools-lambda-python/issues/2928)) +* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump mypy-boto3-logs from 1.28.1 to 1.28.15 ([#2880](https://github.com/aws-powertools/powertools-lambda-python/issues/2880)) * **deps-dev:** bump mypy-boto3-appconfigdata from 1.28.0 to 1.28.15 ([#2879](https://github.com/aws-powertools/powertools-lambda-python/issues/2879)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.11 to 1.28.15 ([#2878](https://github.com/aws-powertools/powertools-lambda-python/issues/2878)) * **deps-dev:** bump mypy-boto3-xray from 1.28.0 to 1.28.15 ([#2881](https://github.com/aws-powertools/powertools-lambda-python/issues/2881)) -* **deps-dev:** bump aws-cdk from 2.89.0 to 2.90.0 ([#2932](https://github.com/aws-powertools/powertools-lambda-python/issues/2932)) * **deps-dev:** bump ruff from 0.0.282 to 0.0.283 ([#2937](https://github.com/aws-powertools/powertools-lambda-python/issues/2937)) * **deps-dev:** bump mypy-boto3-dynamodb from 1.28.0 to 1.28.11 ([#2847](https://github.com/aws-powertools/powertools-lambda-python/issues/2847)) -* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) * **deps-dev:** bump ruff from 0.0.283 to 0.0.284 ([#2940](https://github.com/aws-powertools/powertools-lambda-python/issues/2940)) +* **deps-dev:** bump cfn-lint from 0.79.4 to 0.79.5 ([#2870](https://github.com/aws-powertools/powertools-lambda-python/issues/2870)) +* **deps-dev:** bump cfn-lint from 0.79.6 to 0.79.7 ([#2956](https://github.com/aws-powertools/powertools-lambda-python/issues/2956)) * **deps-dev:** bump mypy-boto3-cloudformation from 1.28.10 to 1.28.12 ([#2864](https://github.com/aws-powertools/powertools-lambda-python/issues/2864)) * **deps-dev:** bump mypy-boto3-cloudwatch from 1.28.0 to 1.28.12 ([#2865](https://github.com/aws-powertools/powertools-lambda-python/issues/2865)) * **deps-dev:** bump cfn-lint from 0.79.3 to 0.79.4 ([#2862](https://github.com/aws-powertools/powertools-lambda-python/issues/2862)) @@ -84,8 +86,8 @@ * **deps-dev:** bump cfn-lint from 0.78.2 to 0.79.3 ([#2854](https://github.com/aws-powertools/powertools-lambda-python/issues/2854)) * **deps-dev:** bump mypy-boto3-lambda from 1.28.0 to 1.28.11 ([#2845](https://github.com/aws-powertools/powertools-lambda-python/issues/2845)) * **deps-dev:** bump xenon from 0.9.0 to 0.9.1 ([#2955](https://github.com/aws-powertools/powertools-lambda-python/issues/2955)) -* **deps-dev:** bump cfn-lint from 0.79.6 to 0.79.7 ([#2956](https://github.com/aws-powertools/powertools-lambda-python/issues/2956)) -* **deps-dev:** bump the boto-typing group with 3 updates ([#2967](https://github.com/aws-powertools/powertools-lambda-python/issues/2967)) +* **deps-dev:** bump aws-cdk from 2.91.0 to 2.92.0 ([#2965](https://github.com/aws-powertools/powertools-lambda-python/issues/2965)) +* **deps-dev:** bump ruff from 0.0.281 to 0.0.282 ([#2905](https://github.com/aws-powertools/powertools-lambda-python/issues/2905)) * **docs:** include the environment variables section in the utilities documentation ([#2925](https://github.com/aws-powertools/powertools-lambda-python/issues/2925)) * **docs:** disable line length rule using older syntax ([#2920](https://github.com/aws-powertools/powertools-lambda-python/issues/2920)) * **maintenance:** enables publishing docs and changelog, running e2e tests only in the main repository ([#2924](https://github.com/aws-powertools/powertools-lambda-python/issues/2924)) From 275116c47ca42027975d4c8799cd6c1832e988de Mon Sep 17 00:00:00 2001 From: "Powertools for AWS Lambda (Python) bot" Date: Fri, 18 Aug 2023 16:25:22 +0000 Subject: [PATCH 92/92] chore: version bump --- aws_lambda_powertools/shared/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/version.py b/aws_lambda_powertools/shared/version.py index 3da2c288c98..e1a3c9425d1 100644 --- a/aws_lambda_powertools/shared/version.py +++ b/aws_lambda_powertools/shared/version.py @@ -1,3 +1,3 @@ """Exposes version constant to avoid circular dependencies.""" -VERSION = "2.22.0" +VERSION = "2.23.0" diff --git a/pyproject.toml b/pyproject.toml index 945aa6a2cc8..bf310af0983 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "2.22.0" +version = "2.23.0" description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity." authors = ["Amazon Web Services"] include = ["aws_lambda_powertools/py.typed", "THIRD-PARTY-LICENSES"]