diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 65dc112dba..071a30e01b 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,12 +1,15 @@ # See here for image contents: https://github.com/microsoft/vscode-dev-containers/blob/v0.212.0/containers/javascript-node/.devcontainer/base.Dockerfile # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster -ARG VARIANT="18-bullseye" +ARG VARIANT="20-bullseye" FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} # This section to install additional OS packages. RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends bash-completion +# Install fnm to manage Node.js versions +RUN curl -fsSL https://fnm.vercel.app/install | bash -s + RUN wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip \ && unzip aws-sam-cli-linux-x86_64.zip -d sam-installation \ && sudo ./sam-installation/install \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e1401b638d..f9033f03d3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ // Append -bullseye or -buster to pin to an OS version. // Use -bullseye variants on local arm64/Apple Silicon. "args": { - "VARIANT": "18-bullseye" + "VARIANT": "20-bullseye" } }, "customizations": { @@ -16,8 +16,7 @@ "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", - "firsttris.vscode-jest-runner", - "amazonwebservices.aws-toolkit-vscode" + "firsttris.vscode-jest-runner" ], "vscode": { "git.enableCommitSigning": true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c9fbf5216c..819d2f3d5a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -67,6 +67,7 @@ body: attributes: label: AWS Lambda function runtime options: + - 20.x - 18.x - 16.x - 14.x diff --git a/.github/actions/cached-node-modules/action.yml b/.github/actions/cached-node-modules/action.yml index d86c8d7b10..42d5db19e7 100644 --- a/.github/actions/cached-node-modules/action.yml +++ b/.github/actions/cached-node-modules/action.yml @@ -1,9 +1,9 @@ name: 'Cached Node Modules' description: 'A simple action to cache node_modules or install them if they are not cached' inputs: - nodeVersion: # id of input + nodeVersion: # id of input description: 'Node.js version to use in the cache key' - default: '18' + default: '20' outputs: cache-hit: description: "Whether the cache was hit or not" @@ -12,6 +12,7 @@ runs: using: "composite" steps: - name: Install npm + # We need to keep this npm version until we drop Node.js 16 support because Node.js 16 doesn't support npm 10 run: npm i -g npm@next-9 shell: bash - name: Cache node modules diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml index 32ee9c0902..122e3844da 100644 --- a/.github/workflows/make-release.yml +++ b/.github/workflows/make-release.yml @@ -26,7 +26,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: "18" + node-version: "20" cache: "npm" - name: Setup auth tokens run: | diff --git a/.github/workflows/make-v2-release.yml b/.github/workflows/make-v2-release.yml index f590a624b1..0c20a1686a 100644 --- a/.github/workflows/make-v2-release.yml +++ b/.github/workflows/make-v2-release.yml @@ -21,7 +21,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: '18' + node-version: '20' cache: 'npm' - name: Setup auth tokens run: | diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index c67d0e58db..acb4a606e7 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -39,7 +39,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: "18" + node-version: "20" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: CDK build diff --git a/.github/workflows/reusable-publish-docs.yml b/.github/workflows/reusable-publish-docs.yml index 9eaace6133..3de8a449ff 100644 --- a/.github/workflows/reusable-publish-docs.yml +++ b/.github/workflows/reusable-publish-docs.yml @@ -47,7 +47,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: "18" + node-version: "20" cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules diff --git a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml index dfd274e6bd..9009f542cf 100644 --- a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml +++ b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml @@ -10,7 +10,7 @@ jobs: NODE_ENV: dev strategy: matrix: - version: [14, 16, 18] + version: [14, 16, 18, 20] fail-fast: false steps: - name: Checkout code @@ -45,7 +45,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: 18 + node-version: 20 cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules @@ -63,7 +63,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: 18 + node-version: 20 cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules @@ -81,7 +81,7 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: 18 + node-version: 20 cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 88da081792..babf9cb2da 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -71,7 +71,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: "18" + node-version: "20" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: Download artifact diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 38c85edcf7..4c2a2b6d55 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -28,7 +28,7 @@ jobs: packages/parameters, packages/idempotency, ] - version: [14, 16, 18] + version: [14, 16, 18, 20] arch: [x86_64, arm64] fail-fast: false steps: @@ -53,11 +53,11 @@ jobs: - name: Setup NodeJS uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 with: - node-version: ${{ matrix.version }} + node-version: '20' - name: Setup dependencies uses: ./.github/actions/cached-node-modules with: - nodeVersion: ${{ matrix.version }} + nodeVersion: '20' - name: Setup AWS credentials uses: aws-actions/configure-aws-credentials@04b98b3f9e85f563fb061be8751a0352327246b0 # v3.0.1 with: diff --git a/.nvmrc b/.nvmrc index a77793ecc5..9de2256827 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/hydrogen +lts/iron diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c96cc10d1..c9a6e3c0b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) ### Bug Fixes diff --git a/docs/contributing/setup.md b/docs/contributing/setup.md index 6960bfcf88..d105488b24 100644 --- a/docs/contributing/setup.md +++ b/docs/contributing/setup.md @@ -23,8 +23,8 @@ graph LR Unless you're using the pre-configured Cloud environment, you'll need the following installed: * [GitHub account](https://github.com/join){target="_blank" rel="nofollow"}. You'll need to be able to fork, clone, and contribute via pull request. -* [Node.js 18.x](https://nodejs.org/download/release/latest-v18.x/){target="_blank" rel="nofollow"}. The repository contains an `.nvmrc` file, so if you use tools like [nvm](https://github.com/nvm-sh/nvm#nvmrc), [fnm](https://github.com/Schniz/fnm) you can switch version quickly. -* [npm 9.x](https://www.npmjs.com/). We use it to install dependencies and manage the workspaces. +* [Node.js 20.x](https://nodejs.org/download/release/latest-v20.x/){target="_blank" rel="nofollow"}. The repository contains an `.nvmrc` file, so if you use tools like [nvm](https://github.com/nvm-sh/nvm#nvmrc), [fnm](https://github.com/Schniz/fnm) you can switch version quickly. +* [npm 10.x](https://www.npmjs.com/). We use it to install dependencies and manage the workspaces. * [Docker](https://docs.docker.com/engine/install/){target="_blank" rel="nofollow"}. We use it to run documentation, and non-JavaScript tooling. * [Fork the repository](https://github.com/aws-powertools/powertools-lambda-typescript/fork). You'll work against your fork of this repository. diff --git a/docs/contributing/testing.md b/docs/contributing/testing.md index 6412297499..0184b095b0 100644 --- a/docs/contributing/testing.md +++ b/docs/contributing/testing.md @@ -84,7 +84,7 @@ To run integration tests you'll need to set up an AWS account and obtain credent * `npm test:e2e -ws` to run all the integration tests for all the modules sequentially * `test:e2e:parallel` to run all the integration tests for all the modules in parallel * `npm test:e2e -w packages/metrics` to run all the integration tests for the `metrics` module -* `npm run test:e2e:nodejs18x -w packages/metrics` to run all the integration tests for the `metrics` module using the `nodejs18x` runtime +* `npm run test:e2e:nodejs20x -w packages/metrics` to run all the integration tests for the `metrics` module using the `nodejs20x` runtime The tests will deploy the necessary AWS resources using AWS CDK, and will run the Lambda functions using the AWS SDK. After that, the tests will verify the Lambda functions behave as expected by checking logs, metrics, traces, and other resources as needed. Finally, the tests will destroy all the AWS resources created at the beginning. diff --git a/docs/core/logger.md b/docs/core/logger.md index 1cc37a50ba..59f38cc6da 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -68,7 +68,7 @@ These settings will be used across all logs emitted: ShoppingCartApiFunction: Type: AWS::Serverless::Function Properties: - Runtime: nodejs18.x + Runtime: nodejs20.x Environment: Variables: LOG_LEVEL: WARN diff --git a/docs/core/metrics.md b/docs/core/metrics.md index a3804b742d..549571dc6e 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -88,7 +88,7 @@ The `Metrics` utility is instantiated outside of the Lambda handler. In doing th HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: nodejs16.x + Runtime: nodejs20.x Environment: Variables: POWERTOOLS_SERVICE_NAME: orders diff --git a/docs/core/tracer.md b/docs/core/tracer.md index 29f3f8a109..6fb06a94c4 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -74,7 +74,7 @@ The `Tracer` utility is instantiated outside of the Lambda handler. In doing thi HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: diff --git a/docs/index.md b/docs/index.md index 6e3653d764..bbbd2dbfe0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,7 +26,7 @@ You can use Powertools for AWS Lambda (TypeScript) in both TypeScript and JavaSc You can install Powertools for AWS Lambda (TypeScript) using one of the following options: -* **Lambda Layer**: [**arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22**](#){: .copyMe}:clipboard: +* **Lambda Layer**: [**arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23**](#){: .copyMe}:clipboard: * **npm**: [`npm install @aws-lambda-powertools/tracer @aws-lambda-powertools/metrics @aws-lambda-powertools/logger`](#){: .copyMe}:clipboard: ### Lambda Layer @@ -41,32 +41,32 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L | Region | Layer ARN | | ---------------- | ------------------------------------------------------------------------------------------------------------ | - | `us-east-1` | [arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-central-2` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `eu-south-2` | [arn:aws:lambda:eu-south-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `af-south-1` | [arn:aws:lambda:af-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | - | `il-central-1` | [arn:aws:lambda:il-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:22](#){: .copyMe}:clipboard: | + | `us-east-1` | [arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-central-2` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `eu-south-2` | [arn:aws:lambda:eu-south-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | + | `il-central-1` | [arn:aws:lambda:il-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:23](#){: .copyMe}:clipboard: | ??? note "Click to expand and copy code snippets for popular frameworks" @@ -77,7 +77,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L Type: AWS::Serverless::Function Properties: Layers: - - !Sub arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22 + - !Sub arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23 ``` If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools` from being bundled since the packages will be already present the Layer: @@ -108,7 +108,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L hello: handler: lambda_function.lambda_handler layers: - - arn:aws:lambda:${aws:region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22 + - arn:aws:lambda:${aws:region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23 ``` If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools` from being bundled since the packages will be already present the Layer: @@ -140,7 +140,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L const powertoolsLayer = lambda.LayerVersion.fromLayerVersionArn( this, 'PowertoolsLayer', - `arn:aws:lambda:${cdk.Stack.of(this).region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22` + `arn:aws:lambda:${cdk.Stack.of(this).region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23` ); new lambda.Function(this, 'Function', { @@ -192,7 +192,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L role = ... handler = "index.handler" runtime = "nodejs16.x" - layers = ["arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22"] + layers = ["arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } ``` @@ -210,7 +210,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L const lambdaFunction = new aws.lambda.Function('function', { layers: [ - pulumi.interpolate`arn:aws:lambda:${aws.getRegionOutput().name}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22` + pulumi.interpolate`arn:aws:lambda:${aws.getRegionOutput().name}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23` ], code: new pulumi.asset.FileArchive('lambda_function_payload.zip'), tracingConfig: { @@ -234,7 +234,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L ? 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:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23 ❯ amplify push -y # Updating an existing function and add the layer @@ -244,7 +244,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L - 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:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23 ? Do you want to edit the local lambda function now? No ``` @@ -254,7 +254,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L 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:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:22 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:23 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. diff --git a/docs/snippets/batch/templates/sam/dynamodb.yaml b/docs/snippets/batch/templates/sam/dynamodb.yaml index c95dea07b7..dfa9e3fd1e 100644 --- a/docs/snippets/batch/templates/sam/dynamodb.yaml +++ b/docs/snippets/batch/templates/sam/dynamodb.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: diff --git a/docs/snippets/batch/templates/sam/kinesis.yaml b/docs/snippets/batch/templates/sam/kinesis.yaml index 032b354a74..3de5232790 100644 --- a/docs/snippets/batch/templates/sam/kinesis.yaml +++ b/docs/snippets/batch/templates/sam/kinesis.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: diff --git a/docs/snippets/batch/templates/sam/sqs.yaml b/docs/snippets/batch/templates/sam/sqs.yaml index 65b91507eb..08dcf89d38 100644 --- a/docs/snippets/batch/templates/sam/sqs.yaml +++ b/docs/snippets/batch/templates/sam/sqs.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: diff --git a/docs/snippets/idempotency/templates/tableCdk.ts b/docs/snippets/idempotency/templates/tableCdk.ts index 8a07d5dc3c..526ce48156 100644 --- a/docs/snippets/idempotency/templates/tableCdk.ts +++ b/docs/snippets/idempotency/templates/tableCdk.ts @@ -18,7 +18,7 @@ export class IdempotencyStack extends Stack { }); const fnHandler = new NodejsFunction(this, 'helloWorldFunction', { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_20_X, handler: 'handler', entry: 'src/index.ts', environment: { diff --git a/docs/snippets/idempotency/templates/tableSam.yaml b/docs/snippets/idempotency/templates/tableSam.yaml index 010ecc89ca..ccd2078aee 100644 --- a/docs/snippets/idempotency/templates/tableSam.yaml +++ b/docs/snippets/idempotency/templates/tableSam.yaml @@ -17,7 +17,7 @@ Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: python3.11 + Runtime: nodejs20.x Handler: app.py Policies: - Statement: diff --git a/docs/snippets/idempotency/templates/tableTerraform.tf b/docs/snippets/idempotency/templates/tableTerraform.tf index 4856f2b0e6..bedd2f6b5e 100644 --- a/docs/snippets/idempotency/templates/tableTerraform.tf +++ b/docs/snippets/idempotency/templates/tableTerraform.tf @@ -28,7 +28,7 @@ resource "aws_dynamodb_table" "IdempotencyTable" { resource "aws_lambda_function" "IdempotencyFunction" { function_name = "IdempotencyFunction" role = aws_iam_role.IdempotencyFunctionRole.arn - runtime = "nodejs18.x" + runtime = "nodejs20.x" handler = "index.handler" filename = "lambda.zip" } diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index b1a5b009be..65852c06ca 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -60,7 +60,7 @@ While we support Amazon DynamoDB as a persistance layer out of the box, you need ???+ note - This utility supports **[AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/){target="_blank"} only**. If you are using the `nodejs18.x` runtime, the AWS SDK for JavaScript v3 is already installed and you can install only the utility. + This utility supports **[AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/){target="_blank"} only**. If you are using the `nodejs18.x` runtime or newer, the AWS SDK for JavaScript v3 is already installed and you can install only the utility. ### IAM Permissions diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index c2b844376e..df89ef8a62 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -44,7 +44,7 @@ Depending on the provider you want to use, install the library and the correspon ``` ???+ tip - If you are using the `nodejs18.x` runtime, the AWS SDK for JavaScript v3 is already installed and you can install the utility only. + If you are using the `nodejs18.x` runtime or newer, the AWS SDK for JavaScript v3 is already installed and you can install the utility only. ### IAM Permissions diff --git a/examples/cdk/CHANGELOG.md b/examples/cdk/CHANGELOG.md index 6e7a04178a..c96c273c4a 100644 --- a/examples/cdk/CHANGELOG.md +++ b/examples/cdk/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package cdk-sample diff --git a/examples/cdk/package.json b/examples/cdk/package.json index 76653f05af..38be2c1ead 100644 --- a/examples/cdk/package.json +++ b/examples/cdk/package.json @@ -1,6 +1,6 @@ { "name": "cdk-sample", - "version": "1.14.2", + "version": "1.15.0", "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com" @@ -25,17 +25,17 @@ "*.js": "npm run lint-fix" }, "devDependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", - "@aws-lambda-powertools/logger": "^1.14.2", - "@aws-lambda-powertools/metrics": "^1.14.2", - "@aws-lambda-powertools/parameters": "^1.14.2", - "@aws-lambda-powertools/tracer": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", + "@aws-lambda-powertools/logger": "^1.15.0", + "@aws-lambda-powertools/metrics": "^1.15.0", + "@aws-lambda-powertools/parameters": "^1.15.0", + "@aws-lambda-powertools/tracer": "^1.15.0", "@aws-sdk/client-ssm": "^3.413.0", "@aws-sdk/lib-dynamodb": "^3.413.0", "@types/aws-lambda": "^8.10.121", "@types/jest": "^29.5.4", "@types/node": "20.6.1", - "aws-cdk": "^2.96.1", + "aws-cdk": "^2.107.0", "esbuild": "^0.19.3", "jest": "^29.7.0", "ts-jest": "^29.1.1", @@ -44,7 +44,7 @@ }, "dependencies": { "@middy/core": "^3.6.2", - "aws-cdk-lib": "^2.96.1", + "aws-cdk-lib": "^2.107.0", "constructs": "^10.2.70", "phin": "^3.7.0", "source-map-support": "^0.5.21" diff --git a/examples/cdk/src/example-stack.ts b/examples/cdk/src/example-stack.ts index b7cfa0d9ed..a7aeb12b4d 100644 --- a/examples/cdk/src/example-stack.ts +++ b/examples/cdk/src/example-stack.ts @@ -11,7 +11,7 @@ import { StringParameter } from 'aws-cdk-lib/aws-ssm'; import { Construct } from 'constructs'; const commonProps: Partial = { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_20_X, tracing: Tracing.ACTIVE, timeout: Duration.seconds(30), logRetention: RetentionDays.ONE_DAY, @@ -112,7 +112,7 @@ class UuidApi extends Construct { super(scope, id); const uuidFn = new NodejsFunction(this, 'UuidFn', { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_20_X, entry: './functions/uuid.ts', }); diff --git a/examples/sam/CHANGELOG.md b/examples/sam/CHANGELOG.md index dddaf3506f..af1652811c 100644 --- a/examples/sam/CHANGELOG.md +++ b/examples/sam/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package sam-example diff --git a/examples/sam/package.json b/examples/sam/package.json index aeb3f5f6a1..ea03d367f5 100644 --- a/examples/sam/package.json +++ b/examples/sam/package.json @@ -1,6 +1,6 @@ { "name": "sam-example", - "version": "1.14.2", + "version": "1.15.0", "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com" @@ -30,10 +30,10 @@ "typescript": "^5.2.2" }, "dependencies": { - "@aws-lambda-powertools/logger": "^1.14.2", - "@aws-lambda-powertools/metrics": "^1.14.2", - "@aws-lambda-powertools/parameters": "^1.14.2", - "@aws-lambda-powertools/tracer": "^1.14.2", + "@aws-lambda-powertools/logger": "^1.15.0", + "@aws-lambda-powertools/metrics": "^1.15.0", + "@aws-lambda-powertools/parameters": "^1.15.0", + "@aws-lambda-powertools/tracer": "^1.15.0", "@aws-sdk/client-dynamodb": "^3.413.0", "@aws-sdk/client-ssm": "^3.413.0", "@aws-sdk/lib-dynamodb": "^3.413.0", diff --git a/examples/sam/template.yaml b/examples/sam/template.yaml index 3f19a4c5d3..39d440f21f 100644 --- a/examples/sam/template.yaml +++ b/examples/sam/template.yaml @@ -31,7 +31,7 @@ Parameters: # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html Globals: Function: - Runtime: nodejs18.x + Runtime: nodejs20.x Architectures: - x86_64 MemorySize: 128 diff --git a/layers/CHANGELOG.md b/layers/CHANGELOG.md index 1f6cc4f185..d9d774faca 100644 --- a/layers/CHANGELOG.md +++ b/layers/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package layers diff --git a/layers/package.json b/layers/package.json index 363539203f..4338132712 100644 --- a/layers/package.json +++ b/layers/package.json @@ -1,6 +1,6 @@ { "name": "layers", - "version": "1.14.2", + "version": "1.15.0", "bin": { "layer": "bin/layers.js" }, @@ -40,7 +40,7 @@ }, "dependencies": { "aws-cdk": "^2.96.1", - "aws-cdk-lib": "^2.96.1", + "aws-cdk-lib": "^2.107.0", "esbuild": "^0.19.3" } } diff --git a/layers/src/layer-publisher-stack.ts b/layers/src/layer-publisher-stack.ts index 6ef6c19fda..f9d37afc31 100644 --- a/layers/src/layer-publisher-stack.ts +++ b/layers/src/layer-publisher-stack.ts @@ -40,6 +40,7 @@ export class LayerPublisherStack extends Stack { Runtime.NODEJS_14_X, Runtime.NODEJS_16_X, Runtime.NODEJS_18_X, + Runtime.NODEJS_20_X, ], license: 'MIT-0', // This is needed because the following regions do not support the compatibleArchitectures property #1400 @@ -47,7 +48,7 @@ export class LayerPublisherStack extends Stack { code: Code.fromAsset(resolve(__dirname), { bundling: { // This is here only because is required by CDK, however it is not used since the bundling is done locally - image: Runtime.NODEJS_18_X.bundlingImage, + image: Runtime.NODEJS_20_X.bundlingImage, // We need to run a command to generate a random UUID to force the bundling to run every time command: [`echo "${randomUUID()}"`], local: { diff --git a/layers/tests/e2e/layerPublisher.test.ts b/layers/tests/e2e/layerPublisher.test.ts index 09aebc671d..6772da71a6 100644 --- a/layers/tests/e2e/layerPublisher.test.ts +++ b/layers/tests/e2e/layerPublisher.test.ts @@ -145,10 +145,14 @@ describe(`Layers E2E tests, publisher stack`, () => { it( 'should have one info log related to coldstart metric', () => { - const logs = invocationLogs.getFunctionLogs('INFO'); + const logs = invocationLogs.getFunctionLogs(); + const emfLogEntry = logs.find((log) => + log.match( + /{"_aws":{"Timestamp":\d+,"CloudWatchMetrics":\[\{"Namespace":"\S+","Dimensions":\[\["service"\]\],"Metrics":\[\{"Name":"ColdStart","Unit":"Count"\}\]\}\]},"service":"\S+","ColdStart":1}/ + ) + ); - expect(logs.length).toBe(1); - expect(logs[0]).toContain('ColdStart'); + expect(emfLogEntry).toBeDefined(); }, TEST_CASE_TIMEOUT ); diff --git a/layers/tests/unit/layer-publisher.test.ts b/layers/tests/unit/layer-publisher.test.ts index a365c34f3d..9f7ff98f70 100644 --- a/layers/tests/unit/layer-publisher.test.ts +++ b/layers/tests/unit/layer-publisher.test.ts @@ -25,7 +25,12 @@ describe('Class: LayerPublisherStack', () => { // Assess template.resourceCountIs('AWS::Lambda::LayerVersion', 1); template.hasResourceProperties('AWS::Lambda::LayerVersion', { - CompatibleRuntimes: ['nodejs14.x', 'nodejs16.x', 'nodejs18.x'], + CompatibleRuntimes: [ + 'nodejs14.x', + 'nodejs16.x', + 'nodejs18.x', + 'nodejs20.x', + ], LicenseInfo: 'MIT-0', /* CompatibleArchitectures: [ 'x86_64', diff --git a/lerna.json b/lerna.json index c14a9b3bf6..3299d1a779 100644 --- a/lerna.json +++ b/lerna.json @@ -12,7 +12,7 @@ "examples/sam", "layers" ], - "version": "1.14.2", + "version": "1.15.0", "npmClient": "npm", "message": "chore(release): %s [skip ci]" } diff --git a/package-lock.json b/package-lock.json index ecda462c43..a425319229 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,11 +72,11 @@ }, "examples/cdk": { "name": "cdk-sample", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { "@middy/core": "^3.6.2", - "aws-cdk-lib": "^2.96.1", + "aws-cdk-lib": "^2.107.0", "constructs": "^10.2.70", "phin": "^3.7.0", "source-map-support": "^0.5.21" @@ -85,17 +85,17 @@ "cdk-app": "bin/cdk-app.js" }, "devDependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", - "@aws-lambda-powertools/logger": "^1.14.2", - "@aws-lambda-powertools/metrics": "^1.14.2", - "@aws-lambda-powertools/parameters": "^1.14.2", - "@aws-lambda-powertools/tracer": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", + "@aws-lambda-powertools/logger": "^1.15.0", + "@aws-lambda-powertools/metrics": "^1.15.0", + "@aws-lambda-powertools/parameters": "^1.15.0", + "@aws-lambda-powertools/tracer": "^1.15.0", "@aws-sdk/client-ssm": "^3.413.0", "@aws-sdk/lib-dynamodb": "^3.413.0", "@types/aws-lambda": "^8.10.121", "@types/jest": "^29.5.4", "@types/node": "20.6.1", - "aws-cdk": "^2.96.1", + "aws-cdk": "^2.107.0", "esbuild": "^0.19.3", "jest": "^29.7.0", "ts-jest": "^29.1.1", @@ -111,13 +111,13 @@ }, "examples/sam": { "name": "sam-example", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/logger": "^1.14.2", - "@aws-lambda-powertools/metrics": "^1.14.2", - "@aws-lambda-powertools/parameters": "^1.14.2", - "@aws-lambda-powertools/tracer": "^1.14.2", + "@aws-lambda-powertools/logger": "^1.15.0", + "@aws-lambda-powertools/metrics": "^1.15.0", + "@aws-lambda-powertools/parameters": "^1.15.0", + "@aws-lambda-powertools/tracer": "^1.15.0", "@aws-sdk/client-dynamodb": "^3.413.0", "@aws-sdk/client-ssm": "^3.413.0", "@aws-sdk/lib-dynamodb": "^3.413.0", @@ -142,11 +142,11 @@ "dev": true }, "layers": { - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { "aws-cdk": "^2.96.1", - "aws-cdk-lib": "^2.96.1", + "aws-cdk-lib": "^2.107.0", "esbuild": "^0.19.3" }, "bin": { @@ -180,9 +180,9 @@ } }, "node_modules/@aws-cdk/asset-awscli-v1": { - "version": "2.2.200", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz", - "integrity": "sha512-Kf5J8DfJK4wZFWT2Myca0lhwke7LwHcHBo+4TvWOGJrFVVKVuuiLCkzPPRBQQVDj0Vtn2NBokZAz8pfMpAqAKg==" + "version": "2.2.201", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.201.tgz", + "integrity": "sha512-INZqcwDinNaIdb5CtW3ez5s943nX5stGBQS6VOP2JDlOFP81hM3fds/9NDknipqfUkZM43dx+HgVvkXYXXARCQ==" }, "node_modules/@aws-cdk/asset-kubectl-v20": { "version": "2.1.2", @@ -195,9 +195,9 @@ "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==" }, "node_modules/@aws-cdk/cli-lib-alpha": { - "version": "2.96.1-alpha.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/cli-lib-alpha/-/cli-lib-alpha-2.96.1-alpha.0.tgz", - "integrity": "sha512-KRPG90986E+TbC9VDHR01R5SUct+aM5CEal8fLEn5hYg79Rp8Haaa96OwPaX/aiZdo+sM0v4fCaLICxG5/QZPg==", + "version": "2.107.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cli-lib-alpha/-/cli-lib-alpha-2.107.0-alpha.0.tgz", + "integrity": "sha512-pgG0wdtW73Y83+8/HwsBdFEjtjOegVHDecFx41mTGhtjHO2NdgoZUX4ab4vm/YNOHIW6zOKFNzGFLi5Q5PfVHA==", "engines": { "node": ">= 14.15.0" } @@ -6007,9 +6007,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.96.1", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.96.1.tgz", - "integrity": "sha512-dCMriGZj2w6/B5+bu45knQM9QmPpDoUMiGCzsxALsOJVu/Fr5QwvmHxRBTc48uaVAOlYN2qQsAcG5H6TXtBJhg==", + "version": "2.107.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.107.0.tgz", + "integrity": "sha512-Hu0KaTpIO8Zuz/qZqn1FXT0xqO/hSjmimgt0mMYkkjsHYzt4xkfFarjes2X4a5PhYv8hSWml1ClfcmW6yEOAzA==", "bin": { "cdk": "bin/cdk" }, @@ -6021,9 +6021,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.96.1", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.96.1.tgz", - "integrity": "sha512-7jo7btYghU0OCx9BUi/CmEL967Udc3PNm45uBxn6P2ipvhuYSLkJj0toNiln8uPmMKdTzZPH2r22kX+7N9NzQw==", + "version": "2.107.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.107.0.tgz", + "integrity": "sha512-eLyTTxthuxpOAN/RdmP0lKenpscwSFatMhEEqcxVd94ikeUUG3od3QQalpCDf5ohNYhJL6JMwhSVmMEtDJMGNQ==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -6037,7 +6037,7 @@ "yaml" ], "dependencies": { - "@aws-cdk/asset-awscli-v1": "^2.2.200", + "@aws-cdk/asset-awscli-v1": "^2.2.201", "@aws-cdk/asset-kubectl-v20": "^2.1.2", "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", "@balena/dockerignore": "^1.0.2", @@ -6046,7 +6046,7 @@ "ignore": "^5.2.4", "jsonschema": "^1.4.1", "minimatch": "^3.1.2", - "punycode": "^2.3.0", + "punycode": "^2.3.1", "semver": "^7.5.4", "table": "^6.8.1", "yaml": "1.10.2" @@ -6247,7 +6247,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/punycode": { - "version": "2.3.0", + "version": "2.3.1", "inBundle": true, "license": "MIT", "engines": { @@ -6332,7 +6332,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/universalify": { - "version": "2.0.0", + "version": "2.0.1", "inBundle": true, "license": "MIT", "engines": { @@ -17781,20 +17781,20 @@ }, "packages/batch": { "name": "@aws-lambda-powertools/batch", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0" }, "packages/commons": { "name": "@aws-lambda-powertools/commons", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0" }, "packages/idempotency": { "name": "@aws-lambda-powertools/idempotency", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "@aws-sdk/util-base64-node": "^3.209.0", "jmespath": "^0.16.0" }, @@ -17825,10 +17825,10 @@ }, "packages/logger": { "name": "@aws-lambda-powertools/logger", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "lodash.merge": "^4.6.2" }, "devDependencies": { @@ -17846,10 +17846,10 @@ }, "packages/metrics": { "name": "@aws-lambda-powertools/metrics", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2" + "@aws-lambda-powertools/commons": "^1.15.0" }, "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", @@ -17868,10 +17868,10 @@ }, "packages/parameters": { "name": "@aws-lambda-powertools/parameters", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "@aws-sdk/util-base64-node": "^3.209.0" }, "devDependencies": { @@ -17914,22 +17914,22 @@ }, "packages/testing": { "name": "@aws-lambda-powertools/testing-utils", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-cdk/cli-lib-alpha": "^2.96.1-alpha.0", + "@aws-cdk/cli-lib-alpha": "^2.107.0-alpha.0", "@aws-sdk/client-lambda": "^3.438.0", "@smithy/util-utf8": "^2.0.0", - "aws-cdk-lib": "^2.96.1", + "aws-cdk-lib": "^2.107.0", "esbuild": "^0.19.3" } }, "packages/tracer": { "name": "@aws-lambda-powertools/tracer", - "version": "1.14.2", + "version": "1.15.0", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "aws-xray-sdk-core": "^3.5.3" }, "devDependencies": { diff --git a/packages/batch/CHANGELOG.md b/packages/batch/CHANGELOG.md index c8eb18dc25..fcca18d252 100644 --- a/packages/batch/CHANGELOG.md +++ b/packages/batch/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/batch diff --git a/packages/batch/package.json b/packages/batch/package.json index ed956b0c1b..5d868945f5 100644 --- a/packages/batch/package.json +++ b/packages/batch/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/batch", - "version": "1.14.2", + "version": "1.15.0", "description": "The batch processing package for the Powertools for AWS Lambda (TypeScript) library.", "author": { "name": "Amazon Web Services", @@ -16,6 +16,7 @@ "test:e2e:nodejs14x": "echo 'Not Implemented'", "test:e2e:nodejs16x": "echo 'Not Implemented'", "test:e2e:nodejs18x": "echo 'Not Implemented'", + "test:e2e:nodejs20x": "echo 'Not Implemented'", "test:e2e": "echo 'Not Implemented'", "watch": "jest --watch", "build": "tsc --build --force", diff --git a/packages/batch/tests/helpers/populateEnvironmentVariables.ts b/packages/batch/tests/helpers/populateEnvironmentVariables.ts index cb0b37f295..9dc602e5f0 100644 --- a/packages/batch/tests/helpers/populateEnvironmentVariables.ts +++ b/packages/batch/tests/helpers/populateEnvironmentVariables.ts @@ -1,7 +1,7 @@ // Reserved variables process.env._X_AMZN_TRACE_ID = '1-abcdef12-3456abcdef123456abcdef12'; process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-lambda-function'; -process.env.AWS_EXECUTION_ENV = 'nodejs18.x'; +process.env.AWS_EXECUTION_ENV = 'nodejs20.x'; process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128'; if ( process.env.AWS_REGION === undefined && diff --git a/packages/commons/CHANGELOG.md b/packages/commons/CHANGELOG.md index d27f118f3d..ca11d6c233 100644 --- a/packages/commons/CHANGELOG.md +++ b/packages/commons/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/commons diff --git a/packages/commons/package.json b/packages/commons/package.json index 3be44fdbea..d880d1cfda 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/commons", - "version": "1.14.2", + "version": "1.15.0", "description": "A shared utility package for Powertools for AWS Lambda (TypeScript) libraries", "author": { "name": "Amazon Web Services", diff --git a/packages/commons/src/config/ConfigService.ts b/packages/commons/src/config/ConfigService.ts index e149c27229..df2d69bd81 100644 --- a/packages/commons/src/config/ConfigService.ts +++ b/packages/commons/src/config/ConfigService.ts @@ -35,6 +35,13 @@ abstract class ConfigService { */ public abstract getXrayTraceId(): string | undefined; + /** + * It returns true if the `POWERTOOLS_DEV` environment variable is set to truthy value. + * + * @returns {boolean} + */ + public abstract isDevMode(): boolean; + /** * It returns true if the string value represents a boolean true value. * diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index 59183a15d4..f222fccfb8 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -13,11 +13,12 @@ import { ConfigService } from './ConfigService'; * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables */ -class EnvironmentVariablesService extends ConfigService { +class EnvironmentVariablesService implements ConfigService { /** * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables * @protected */ + protected devModeVariable = 'POWERTOOLS_DEV'; protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; // Reserved environment variables private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; @@ -71,6 +72,15 @@ class EnvironmentVariablesService extends ConfigService { return xRayTraceData?.Sampled === '1'; } + /** + * It returns true if the `POWERTOOLS_DEV` environment variable is set to truthy value. + * + * @returns {boolean} + */ + public isDevMode(): boolean { + return this.isValueTrue(this.get(this.devModeVariable)); + } + /** * It returns true if the string value represents a boolean true value. * diff --git a/packages/commons/src/version.ts b/packages/commons/src/version.ts index c42c660c40..7f338fc57f 100644 --- a/packages/commons/src/version.ts +++ b/packages/commons/src/version.ts @@ -1,2 +1,2 @@ // this file is auto generated, do not modify -export const PT_VERSION = '1.13.1'; +export const PT_VERSION = '1.15.0'; diff --git a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts index 055a57ac61..b1e90b6b08 100644 --- a/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/commons/tests/unit/config/EnvironmentVariablesService.test.ts @@ -163,4 +163,54 @@ describe('Class: EnvironmentVariablesService', () => { } ); }); + + describe('Method: isDevMode', () => { + test('it returns true if the environment variable POWERTOOLS_DEV is "true"', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'true'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(true); + }); + + test('it returns false if the environment variable POWERTOOLS_DEV is "false"', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'false'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(false); + }); + + test('it returns false if the environment variable POWERTOOLS_DEV is NOT set', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'somethingsilly'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(false); + }); + + test('it returns false if the environment variable POWERTOOLS_DEV is "somethingsilly"', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'somethingsilly'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(false); + }); + }); }); diff --git a/packages/idempotency/CHANGELOG.md b/packages/idempotency/CHANGELOG.md index 82ff512d9e..b3d489c6b6 100644 --- a/packages/idempotency/CHANGELOG.md +++ b/packages/idempotency/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/idempotency diff --git a/packages/idempotency/package.json b/packages/idempotency/package.json index 03f72769cd..1701e00c13 100644 --- a/packages/idempotency/package.json +++ b/packages/idempotency/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/idempotency", - "version": "1.14.2", + "version": "1.15.0", "description": "The idempotency package for the Powertools for AWS Lambda (TypeScript) library. It provides options to make your Lambda functions idempotent and safe to retry.", "author": { "name": "Amazon Web Services", @@ -16,6 +16,7 @@ "test:e2e:nodejs14x": "RUNTIME=nodejs14x jest --group=e2e", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch", "build": "tsc --build --force", @@ -80,7 +81,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "@aws-sdk/util-base64-node": "^3.209.0", "jmespath": "^0.16.0" }, diff --git a/packages/idempotency/tests/e2e/idempotentDecorator.test.ts b/packages/idempotency/tests/e2e/idempotentDecorator.test.ts index 87293d0eb3..ec740e0f03 100644 --- a/packages/idempotency/tests/e2e/idempotentDecorator.test.ts +++ b/packages/idempotency/tests/e2e/idempotentDecorator.test.ts @@ -14,7 +14,6 @@ import { ScanCommand } from '@aws-sdk/lib-dynamodb'; import { createHash } from 'node:crypto'; import { invokeFunction, - isValidRuntimeKey, TestInvocationLogs, TestStack, } from '@aws-lambda-powertools/testing-utils'; @@ -23,12 +22,6 @@ import { join } from 'node:path'; import { Duration } from 'aws-cdk-lib'; import { AttributeType } from 'aws-cdk-lib/aws-dynamodb'; -const runtime: string = process.env.RUNTIME || 'nodejs18x'; - -if (!isValidRuntimeKey(runtime)) { - throw new Error(`Invalid runtime key value: ${runtime}`); -} - const dynamoDBClient = new DynamoDBClient({}); describe('Idempotency e2e test decorator, default settings', () => { diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index a26534d828..c643f62987 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/logger diff --git a/packages/logger/package.json b/packages/logger/package.json index e16627d1ec..a0027b28c5 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/logger", - "version": "1.14.2", + "version": "1.15.0", "description": "The logging package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -16,6 +16,7 @@ "test:e2e:nodejs14x": "RUNTIME=nodejs14x jest --group=e2e", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch --group=unit", "build": "tsc --build --force", @@ -54,7 +55,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "lodash.merge": "^4.6.2" }, "keywords": [ diff --git a/packages/logger/src/config/EnvironmentVariablesService.ts b/packages/logger/src/config/EnvironmentVariablesService.ts index d2eae54972..edace97de3 100644 --- a/packages/logger/src/config/EnvironmentVariablesService.ts +++ b/packages/logger/src/config/EnvironmentVariablesService.ts @@ -22,7 +22,6 @@ class EnvironmentVariablesService // Reserved environment variables private awsRegionVariable = 'AWS_REGION'; private currentEnvironmentVariable = 'ENVIRONMENT'; - private devModeVariable = 'POWERTOOLS_DEV'; private functionNameVariable = 'AWS_LAMBDA_FUNCTION_NAME'; private functionVersionVariable = 'AWS_LAMBDA_FUNCTION_VERSION'; private logEventVariable = 'POWERTOOLS_LOGGER_LOG_EVENT'; @@ -107,17 +106,6 @@ class EnvironmentVariablesService return value && value.length > 0 ? Number(value) : undefined; } - - /** - * It returns true if the POWERTOOLS_DEV environment variable is set to truthy value. - * - * @returns {boolean} - */ - public isDevMode(): boolean { - const value = this.get(this.devModeVariable); - - return this.isValueTrue(value); - } } export { EnvironmentVariablesService }; diff --git a/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts b/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts index fb6b7ed232..b5a212ab1a 100644 --- a/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts +++ b/packages/logger/tests/unit/config/EnvironmentVariablesService.test.ts @@ -152,54 +152,4 @@ describe('Class: EnvironmentVariablesService', () => { expect(value).toEqual(0.01); }); }); - - describe('Method: isDevMode', () => { - test('it returns true if the environment variable POWERTOOLS_DEV is "true"', () => { - // Prepare - process.env.POWERTOOLS_DEV = 'true'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.isDevMode(); - - // Assess - expect(value).toEqual(true); - }); - - test('it returns false if the environment variable POWERTOOLS_DEV is "false"', () => { - // Prepare - process.env.POWERTOOLS_DEV = 'false'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.isDevMode(); - - // Assess - expect(value).toEqual(false); - }); - - test('it returns false if the environment variable POWERTOOLS_DEV is NOT set', () => { - // Prepare - process.env.POWERTOOLS_DEV = 'somethingsilly'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.isDevMode(); - - // Assess - expect(value).toEqual(false); - }); - - test('it returns false if the environment variable POWERTOOLS_DEV is "somethingsilly"', () => { - // Prepare - process.env.POWERTOOLS_DEV = 'somethingsilly'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.isDevMode(); - - // Assess - expect(value).toEqual(false); - }); - }); }); diff --git a/packages/logger/tests/unit/formatter/PowertoolLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolLogFormatter.test.ts index 02e1e2a303..9176ce8d8d 100644 --- a/packages/logger/tests/unit/formatter/PowertoolLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolLogFormatter.test.ts @@ -3,7 +3,7 @@ * * @group unit/logger/all */ -import { AssertionError, strictEqual } from 'assert'; +import { AssertionError } from 'node:assert'; import { PowertoolLogFormatter } from '../../../src/formatter'; import { UnformattedAttributes } from '../../../src/types'; @@ -97,215 +97,154 @@ describe('Class: PowertoolLogFormatter', () => { test('when an error of type Error is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - throw new Error('Ouch!'); - }; - - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(Error); - const formattedError = formatter.formatError(error); - expect(formattedError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+$/ - ), - message: 'Ouch!', - name: 'Error', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } - expect(shouldThrow).toThrowError(expect.any(Error)); + // Act & Assess + const formattedError = formatter.formatError(new Error('Ouch!')); + expect(formattedError).toEqual({ + location: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+$/ + ), + message: 'Ouch!', + name: 'Error', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error of type ReferenceError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - // This is a reference error purposely to test the formatter - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - doesNotExist; - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(Error); - const formattedReferenceError = formatter.formatError(error); - expect(formattedReferenceError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+$/ - ), - message: 'doesNotExist is not defined', - name: 'ReferenceError', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } - - expect(shouldThrow).toThrowError(expect.any(ReferenceError)); + // Act & Assess + const formattedReferenceError = formatter.formatError( + new ReferenceError('doesNotExist is not defined') + ); + expect(formattedReferenceError).toEqual({ + location: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+$/ + ), + message: 'doesNotExist is not defined', + name: 'ReferenceError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error of type AssertionError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - strictEqual(1, 2); - }; - - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(AssertionError); - const formattedAssertionError = formatter.formatError( - error - ); - expect(formattedAssertionError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+/ - ), - message: expect.stringMatching( - /Expected values to be strictly equal/ - ), - name: 'AssertionError', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } - expect(shouldThrow).toThrowError(expect.any(AssertionError)); + // Act & Assess + const formattedAssertionError = formatter.formatError( + new AssertionError({ + message: 'Expected values to be strictly equal', + actual: 1, + expected: 2, + operator: 'strictEqual', + }) + ); + expect(formattedAssertionError).toEqual({ + location: expect.stringMatching( + /(node:)*internal\/assert\/assertion_error(.js)*:[0-9]+$/ + ), + message: expect.stringMatching(/Expected values to be strictly equal/), + name: 'AssertionError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error of type RangeError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - throw new RangeError('The argument must be between 10 and 20'); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(RangeError); - const formattedRangeError = formatter.formatError(error); - expect(formattedRangeError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+/ - ), - message: 'The argument must be between 10 and 20', - name: 'RangeError', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } + // Act & Assess + const formattedRangeError = formatter.formatError( + new RangeError('The argument must be between 10 and 20') + ); + expect(formattedRangeError).toEqual({ + location: expect.stringMatching(/PowertoolLogFormatter.test.ts:[0-9]+/), + message: 'The argument must be between 10 and 20', + name: 'RangeError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); + }); + + test('when an error of type ReferenceError is passed, it returns an object with expected structure and values', () => { + // Prepare + const formatter = new PowertoolLogFormatter(); - expect(shouldThrow).toThrowError(expect.any(RangeError)); + // Act & Assess + const formattedError = formatter.formatError( + new ReferenceError('foo is not defined') + ); + expect(formattedError).toEqual({ + location: expect.stringMatching(/PowertoolLogFormatter.test.ts:[0-9]+/), + message: 'foo is not defined', + name: 'ReferenceError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error of type SyntaxError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - eval('foo bar'); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(SyntaxError); - const formattedSyntaxError = formatter.formatError(error); - expect(formattedSyntaxError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+/ - ), - message: 'Unexpected identifier', - name: 'SyntaxError', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } - - expect(shouldThrow).toThrowError(expect.any(SyntaxError)); + // Act & Assess + const formattedSyntaxError = formatter.formatError( + new SyntaxError(`Unexpected identifier 'bar'`) + ); + expect(formattedSyntaxError).toEqual({ + location: expect.stringMatching(/PowertoolLogFormatter.test.ts:[0-9]+/), + message: `Unexpected identifier 'bar'`, + name: 'SyntaxError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error of type TypeError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - // This is a reference error purposely to test the formatter - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - null.foo(); - }; - - // Act - try { - shouldThrow(); - } catch (error) { - // TODO: review message content assertion (see Issue #304) - // Assess - expect(error).toBeInstanceOf(Error); - const formattedTypeError = formatter.formatError(error); - expect(formattedTypeError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+/ - ), - message: expect.stringMatching(/Cannot read propert/), - name: 'TypeError', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } - expect(shouldThrow).toThrowError(expect.any(TypeError)); + // Act & Assess + const formattedTypeError = formatter.formatError( + new TypeError(`Cannot read property 'foo' of null`) + ); + expect(formattedTypeError).toEqual({ + location: expect.stringMatching(/PowertoolLogFormatter.test.ts:[0-9]+/), + message: expect.stringMatching(/Cannot read propert/), + name: 'TypeError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error of type URIError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolLogFormatter(); - const shouldThrow = (): void => { - decodeURIComponent('%'); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(URIError); - const formattedURIError = formatter.formatError(error); - expect(formattedURIError).toEqual({ - location: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+/ - ), - message: 'URI malformed', - name: 'URIError', - stack: expect.stringMatching( - /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ - ), - }); - } - - expect(shouldThrow).toThrowError(expect.any(URIError)); + // Act & Assess + const formattedURIError = formatter.formatError( + new URIError('URI malformed') + ); + expect(formattedURIError).toEqual({ + location: expect.stringMatching(/PowertoolLogFormatter.test.ts:[0-9]+/), + message: 'URI malformed', + name: 'URIError', + stack: expect.stringMatching( + /PowertoolLogFormatter.test.ts:[0-9]+:[0-9]+/ + ), + }); }); test('when an error with cause of type Error is formatted, the cause key is included and formatted', () => { diff --git a/packages/metrics/CHANGELOG.md b/packages/metrics/CHANGELOG.md index fb55827d8e..6230370894 100644 --- a/packages/metrics/CHANGELOG.md +++ b/packages/metrics/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) ### Bug Fixes diff --git a/packages/metrics/package.json b/packages/metrics/package.json index 86dd8990f6..c5a8ac92f3 100644 --- a/packages/metrics/package.json +++ b/packages/metrics/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/metrics", - "version": "1.14.2", + "version": "1.15.0", "description": "The metrics package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -16,6 +16,7 @@ "test:e2e:nodejs14x": "RUNTIME=nodejs14x jest --group=e2e", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --group=unit --watch ", "build": "tsc --build --force", @@ -56,7 +57,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2" + "@aws-lambda-powertools/commons": "^1.15.0" }, "keywords": [ "aws", diff --git a/packages/metrics/src/Metrics.ts b/packages/metrics/src/Metrics.ts index 5bf9fba97f..f968d9d70b 100644 --- a/packages/metrics/src/Metrics.ts +++ b/packages/metrics/src/Metrics.ts @@ -1,4 +1,5 @@ import type { Callback, Context, Handler } from 'aws-lambda'; +import { Console } from 'node:console'; import { Utility } from '@aws-lambda-powertools/commons'; import type { MetricsInterface } from './MetricsInterface'; import { @@ -109,6 +110,18 @@ import { * ``` */ class Metrics extends Utility implements MetricsInterface { + /** + * Console instance used to print logs. + * + * In AWS Lambda, we create a new instance of the Console class so that we can have + * full control over the output of the logs. In testing environments, we use the + * default console instance. + * + * This property is initialized in the constructor in setOptions(). + * + * @private + */ + private console!: Console; private customConfigService?: ConfigServiceInterface; private defaultDimensions: Dimensions = {}; private dimensions: Dimensions = {}; @@ -388,7 +401,7 @@ class Metrics extends Utility implements MetricsInterface { ); } const target = this.serializeMetrics(); - console.log(JSON.stringify(target)); + this.console.log(JSON.stringify(target)); this.clearMetrics(); this.clearDimensions(); this.clearMetadata(); @@ -591,6 +604,24 @@ class Metrics extends Utility implements MetricsInterface { } } + /** + * It initializes console property as an instance of the internal version of Console() class (PR #748) + * or as the global node console if the `POWERTOOLS_DEV' env variable is set and has truthy value. + * + * @private + * @returns {void} + */ + private setConsole(): void { + if (!this.getEnvVarsService().isDevMode()) { + this.console = new Console({ + stdout: process.stdout, + stderr: process.stderr, + }); + } else { + this.console = console; + } + } + /** * Sets the custom config service to be used. * @@ -640,6 +671,7 @@ class Metrics extends Utility implements MetricsInterface { } = options; this.setEnvVarsService(); + this.setConsole(); this.setCustomConfigService(customConfigService); this.setNamespace(namespace); this.setService(serviceName); diff --git a/packages/metrics/src/config/ConfigServiceInterface.ts b/packages/metrics/src/config/ConfigServiceInterface.ts index ea1c127db6..72ddf7c4f4 100644 --- a/packages/metrics/src/config/ConfigServiceInterface.ts +++ b/packages/metrics/src/config/ConfigServiceInterface.ts @@ -2,6 +2,12 @@ interface ConfigServiceInterface { get?(name: string): string; getNamespace(): string; getServiceName(): string; + /** + * It returns the value of the POWERTOOLS_DEV environment variable. + * + * @returns {boolean} + */ + isDevMode(): boolean; } export { ConfigServiceInterface }; diff --git a/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts b/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts index 332636210e..a0ab289392 100644 --- a/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts +++ b/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts @@ -12,7 +12,7 @@ import { GetMetricStatisticsCommand, } from '@aws-sdk/client-cloudwatch'; import { join } from 'node:path'; -import { getMetrics } from '../helpers/metricsUtils'; +import { getMetrics, sortDimensions } from '../helpers/metricsUtils'; import { MetricsTestNodejsFunction } from '../helpers/resources'; import { commonEnvironmentVars, @@ -98,7 +98,9 @@ describe(`Metrics E2E tests, basic features decorator usage`, () => { expect(coldStartMetrics.Metrics?.length).toBe(1); const coldStartMetric = coldStartMetrics.Metrics?.[0]; - expect(coldStartMetric?.Dimensions).toStrictEqual(expectedDimensions); + expect(sortDimensions(coldStartMetric?.Dimensions)).toStrictEqual( + sortDimensions(expectedDimensions) + ); // Check coldstart metric value const adjustedStartTime = new Date(startTime.getTime() - ONE_MINUTE); @@ -167,7 +169,9 @@ describe(`Metrics E2E tests, basic features decorator usage`, () => { Value: expectedExtraDimension.MyExtraDimension, }, ]; - expect(metric?.Dimensions).toStrictEqual(expectedDimensions); + expect(sortDimensions(metric?.Dimensions)).toStrictEqual( + sortDimensions(expectedDimensions) + ); // Check coldstart metric value const adjustedStartTime = new Date( diff --git a/packages/metrics/tests/e2e/basicFeatures.manual.test.ts b/packages/metrics/tests/e2e/basicFeatures.manual.test.ts index b22861ab16..b984cffd54 100644 --- a/packages/metrics/tests/e2e/basicFeatures.manual.test.ts +++ b/packages/metrics/tests/e2e/basicFeatures.manual.test.ts @@ -12,7 +12,7 @@ import { GetMetricStatisticsCommand, } from '@aws-sdk/client-cloudwatch'; import { join } from 'node:path'; -import { getMetrics } from '../helpers/metricsUtils'; +import { getMetrics, sortDimensions } from '../helpers/metricsUtils'; import { MetricsTestNodejsFunction } from '../helpers/resources'; import { commonEnvironmentVars, @@ -156,7 +156,9 @@ describe(`Metrics E2E tests, manual usage`, () => { Value: expectedExtraDimension.MyExtraDimension, }, ]; - expect(metric?.Dimensions).toStrictEqual(expectedDimensions); + expect(sortDimensions(metric?.Dimensions)).toStrictEqual( + sortDimensions(expectedDimensions) + ); // Check coldstart metric value const adjustedStartTime = new Date( diff --git a/packages/metrics/tests/helpers/metricsUtils.ts b/packages/metrics/tests/helpers/metricsUtils.ts index 5254b474cb..674efa370f 100644 --- a/packages/metrics/tests/helpers/metricsUtils.ts +++ b/packages/metrics/tests/helpers/metricsUtils.ts @@ -5,7 +5,10 @@ import { CloudWatchClient, ListMetricsCommand, } from '@aws-sdk/client-cloudwatch'; -import type { ListMetricsCommandOutput } from '@aws-sdk/client-cloudwatch'; +import type { + Dimension, + ListMetricsCommandOutput, +} from '@aws-sdk/client-cloudwatch'; import type { Context, Handler } from 'aws-lambda'; import type { LambdaInterface } from '@aws-lambda-powertools/commons'; @@ -66,4 +69,7 @@ const setupDecoratorLambdaHandler = ( return handler; }; -export { getMetrics, setupDecoratorLambdaHandler }; +const sortDimensions = (dimensions?: Dimension[]): Dimension[] | undefined => + dimensions?.sort((a, b) => (a.Name || '').localeCompare(b?.Name || '')); + +export { getMetrics, setupDecoratorLambdaHandler, sortDimensions }; diff --git a/packages/metrics/tests/unit/Metrics.test.ts b/packages/metrics/tests/unit/Metrics.test.ts index 936ea142eb..c613b0535d 100644 --- a/packages/metrics/tests/unit/Metrics.test.ts +++ b/packages/metrics/tests/unit/Metrics.test.ts @@ -24,6 +24,13 @@ import { EnvironmentVariablesService, } from '../../src/config'; +jest.mock('node:console', () => ({ + ...jest.requireActual('node:console'), + Console: jest.fn().mockImplementation(() => ({ + log: jest.fn(), + })), +})); +jest.spyOn(console, 'warn').mockImplementation(() => ({})); const mockDate = new Date(1466424490000); const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate); jest.spyOn(console, 'log').mockImplementation(); @@ -234,6 +241,9 @@ describe('Class: Metrics', () => { getServiceName(): string { return 'test-service'; }, + isDevMode(): boolean { + return false; + }, }; const metricsOptions: MetricsOptions = { customConfigService: configService, @@ -703,7 +713,7 @@ describe('Class: Metrics', () => { test('it should publish metrics when the array of values reaches the maximum size', () => { // Prepare const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); - const consoleSpy = jest.spyOn(console, 'log'); + const consoleSpy = jest.spyOn(metrics['console'], 'log'); const metricName = 'test-metric'; // Act @@ -1246,7 +1256,9 @@ describe('Class: Metrics', () => { // Prepare const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); metrics.addMetric('test-metric', MetricUnits.Count, 10); - const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleLogSpy = jest + .spyOn(metrics['console'], 'log') + .mockImplementation(); const mockData: EmfOutput = { _aws: { Timestamp: mockDate.getTime(), @@ -2183,4 +2195,15 @@ describe('Class: Metrics', () => { ); }); }); + + describe('Feature: POWERTOOLS_DEV', () => { + it('uses the global console object when the environment variable is set', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'true'; + const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); + + // Act & Assess + expect(metrics['console']).toEqual(console); + }); + }); }); diff --git a/packages/metrics/tests/unit/middleware/middy.test.ts b/packages/metrics/tests/unit/middleware/middy.test.ts index 5713bcbe9c..5c1e22af48 100644 --- a/packages/metrics/tests/unit/middleware/middy.test.ts +++ b/packages/metrics/tests/unit/middleware/middy.test.ts @@ -3,27 +3,29 @@ * * @group unit/metrics/middleware */ -import { - Metrics, - MetricUnits, - logMetrics, - MetricResolution, -} from '../../../../metrics/src'; +import { Metrics, MetricUnits, logMetrics } from '../../../../metrics/src'; import middy from '@middy/core'; import { ExtraOptions } from '../../../src/types'; import { cleanupMiddlewares } from '@aws-lambda-powertools/commons/lib/middleware'; import { helloworldContext as dummyContext } from '@aws-lambda-powertools/commons/lib/samples/resources/contexts/hello-world'; import { CustomEvent as dummyEvent } from '@aws-lambda-powertools/commons/lib/samples/resources/events/custom/index'; -const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); -const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); +jest.mock('node:console', () => ({ + ...jest.requireActual('node:console'), + Console: jest.fn().mockImplementation(() => ({ + log: jest.fn(), + })), +})); +jest.spyOn(console, 'warn').mockImplementation(() => ({})); const mockDate = new Date(1466424490000); jest.spyOn(global, 'Date').mockImplementation(() => mockDate); describe('Middy middleware', () => { + const ENVIRONMENT_VARIABLES = process.env; + beforeEach(() => { - jest.resetModules(); jest.clearAllMocks(); + process.env = { ...ENVIRONMENT_VARIABLES }; }); describe('throwOnEmptyMetrics', () => { @@ -33,24 +35,13 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('do nothing'); - }; - - const handler = middy(lambdaHandler).use( + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { throwOnEmptyMetrics: true }) ); - try { - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - } catch (e) { - expect((e).message).toBe( - 'The number of metrics recorded must be higher than zero' - ); - } + await expect(handler(dummyEvent, dummyContext)).rejects.toThrowError( + 'The number of metrics recorded must be higher than zero' + ); }); test('should not throw on empty metrics if set to false', async () => { @@ -59,22 +50,14 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('do nothing'); - }; - - const handler = middy(lambdaHandler).use( + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { throwOnEmptyMetrics: false }) ); - try { - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - } catch (e) { - fail(`Should not throw but got the following Error: ${e}`); - } + // Act & Assess + await expect( + handler(dummyEvent, dummyContext) + ).resolves.not.toThrowError(); }); test('should not throw on empty metrics if not set, but should log a warning', async () => { @@ -83,10 +66,10 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - const lambdaHandler = async (): Promise => { - console.log('do nothing'); - }; - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); + const handler = middy(async (): Promise => undefined).use( + logMetrics([metrics]) + ); // Act & Assess await expect( @@ -106,27 +89,27 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('{"message": "do nothing"}'); - }; - - const handler = middy(lambdaHandler).use( + const consoleSpy = jest + .spyOn(metrics['console'], 'log') + .mockImplementation(); + // Monkey patch the singleMetric method to return the metrics instance + // so that we can assert on the console output + jest.spyOn(metrics, 'singleMetric').mockImplementation(() => metrics); + + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { captureColdStartMetric: true }) ); - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked! again') - ); + // Act + await handler(dummyEvent, dummyContext); + await handler(dummyEvent, dummyContext); + + // Assess const loggedData = [ JSON.parse(consoleSpy.mock.calls[0][0]), JSON.parse(consoleSpy.mock.calls[1][0]), ]; - - expect(console.log).toBeCalledTimes(5); + expect(consoleSpy).toBeCalledTimes(2); expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics.length).toBe(1); expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics[0].Name).toBe( 'ColdStart' @@ -143,27 +126,23 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('{"message": "do nothing"}'); - }; - - const handler = middy(lambdaHandler).use( + const consoleSpy = jest + .spyOn(metrics['console'], 'log') + .mockImplementation(); + // Monkey patch the singleMetric method to return the metrics instance + // so that we can assert on the console output + jest.spyOn(metrics, 'singleMetric').mockImplementation(() => metrics); + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { captureColdStartMetric: false }) ); - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked! again') - ); - const loggedData = [ - JSON.parse(consoleSpy.mock.calls[0][0]), - JSON.parse(consoleSpy.mock.calls[1][0]), - ]; + // Act + await handler(dummyEvent, dummyContext); + + // Assess + const loggedData = JSON.parse(consoleSpy.mock.calls[0][0]); - expect(loggedData[0]._aws).toBe(undefined); + expect(loggedData._aws.CloudWatchMetrics[0].Metrics.length).toBe(0); }); test('should not throw on empty metrics if not set', async () => { @@ -172,25 +151,12 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('{"message": "do nothing"}'); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); - - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked! again') + const handler = middy(async (): Promise => undefined).use( + logMetrics(metrics) ); - const loggedData = [ - JSON.parse(consoleSpy.mock.calls[0][0]), - JSON.parse(consoleSpy.mock.calls[1][0]), - ]; - expect(loggedData[0]._aws).toBe(undefined); + // Act & Assess + await expect(handler(dummyEvent, dummyContext)).resolves.not.toThrow(); }); }); @@ -201,21 +167,17 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const cosoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy(async (): Promise => { metrics.addMetric('successfulBooking', MetricUnits.Count, 2); metrics.addMetric('successfulBooking', MetricUnits.Count, 1); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + }).use(logMetrics(metrics)); // Act - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); + await handler(dummyEvent, dummyContext); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(cosoleSpy).toHaveBeenNthCalledWith( 1, JSON.stringify({ _aws: { @@ -240,49 +202,22 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); - }; + const consoleSpy = jest.spyOn(metrics['console'], 'log'); const metricsOptions: ExtraOptions = { throwOnEmptyMetrics: true, defaultDimensions: { environment: 'prod', aws_region: 'eu-west-1' }, captureColdStartMetric: true, }; - const handler = middy(lambdaHandler).use( - logMetrics(metrics, metricsOptions) - ); + const handler = middy(async (): Promise => { + metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + }).use(logMetrics(metrics, metricsOptions)); // Act - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); + await handler(dummyEvent, dummyContext); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, - JSON.stringify({ - _aws: { - Timestamp: 1466424490000, - CloudWatchMetrics: [ - { - Namespace: 'serverlessAirline', - Dimensions: [ - ['service', 'environment', 'aws_region', 'function_name'], - ], - Metrics: [{ Name: 'ColdStart', Unit: 'Count' }], - }, - ], - }, - service: 'orders', - environment: 'prod', - aws_region: 'eu-west-1', - function_name: 'foo-bar-function', - ColdStart: 1, - }) - ); - expect(console.log).toHaveBeenNthCalledWith( - 2, JSON.stringify({ _aws: { Timestamp: 1466424490000, @@ -308,20 +243,16 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy(async (): Promise => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + }).use(logMetrics(metrics)); // Act - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); + await handler(dummyEvent, dummyContext); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, JSON.stringify({ _aws: { @@ -346,24 +277,20 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy(async (): Promise => { metrics.addMetric('successfulBooking', MetricUnits.Count, 1); - }; - const metricsOptions: ExtraOptions = { - throwOnEmptyMetrics: true, - }; - const handler = middy(lambdaHandler).use( - logMetrics([metrics], metricsOptions) + }).use( + logMetrics(metrics, { + throwOnEmptyMetrics: true, + }) ); // Act - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); + await handler(dummyEvent, dummyContext); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, JSON.stringify({ _aws: { @@ -426,100 +353,4 @@ describe('Middy middleware', () => { expect(publishStoredMetricsSpy).toBeCalledTimes(2); }); }); - describe('Metrics resolution', () => { - test('serialized metrics in EMF format should not contain `StorageResolution` as key if `60` is set', async () => { - // Prepare - const metrics = new Metrics({ - namespace: 'serverlessAirline', - serviceName: 'orders', - }); - - const lambdaHandler = (): void => { - metrics.addMetric( - 'successfulBooking', - MetricUnits.Count, - 1, - MetricResolution.Standard - ); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); - - // Act - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - - // Assess - expect(console.log).toHaveBeenCalledWith( - JSON.stringify({ - _aws: { - Timestamp: 1466424490000, - CloudWatchMetrics: [ - { - Namespace: 'serverlessAirline', - Dimensions: [['service']], - Metrics: [ - { - Name: 'successfulBooking', - Unit: 'Count', - }, - ], - }, - ], - }, - service: 'orders', - successfulBooking: 1, - }) - ); - }); - - test('Should be StorageResolution `1` if MetricResolution is set to `High`', async () => { - // Prepare - const metrics = new Metrics({ - namespace: 'serverlessAirline', - serviceName: 'orders', - }); - - const lambdaHandler = (): void => { - metrics.addMetric( - 'successfulBooking', - MetricUnits.Count, - 1, - MetricResolution.High - ); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); - - // Act - await handler(dummyEvent, dummyContext, () => - console.log('Lambda invoked!') - ); - - // Assess - expect(console.log).toHaveBeenCalledWith( - JSON.stringify({ - _aws: { - Timestamp: 1466424490000, - CloudWatchMetrics: [ - { - Namespace: 'serverlessAirline', - Dimensions: [['service']], - Metrics: [ - { - Name: 'successfulBooking', - Unit: 'Count', - StorageResolution: 1, - }, - ], - }, - ], - }, - service: 'orders', - successfulBooking: 1, - }) - ); - }); - }); }); diff --git a/packages/parameters/CHANGELOG.md b/packages/parameters/CHANGELOG.md index b5075d03ae..b3e65b8b4f 100644 --- a/packages/parameters/CHANGELOG.md +++ b/packages/parameters/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/parameters diff --git a/packages/parameters/package.json b/packages/parameters/package.json index f9a4957858..bafe6950a3 100644 --- a/packages/parameters/package.json +++ b/packages/parameters/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/parameters", - "version": "1.14.2", + "version": "1.15.0", "description": "The parameters package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -16,6 +16,7 @@ "test:e2e:nodejs14x": "RUNTIME=nodejs14x jest --group=e2e", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch", "build": "tsc --build --force", @@ -147,7 +148,7 @@ "aws-sdk-client-mock-jest": "^3.0.0" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "@aws-sdk/util-base64-node": "^3.209.0" }, "peerDependencies": { diff --git a/packages/testing/CHANGELOG.md b/packages/testing/CHANGELOG.md index 252e8ec557..69a226a073 100644 --- a/packages/testing/CHANGELOG.md +++ b/packages/testing/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/testing-utils diff --git a/packages/testing/package.json b/packages/testing/package.json index 04e33c5c47..173ac19172 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/testing-utils", - "version": "1.14.2", + "version": "1.15.0", "description": "A package containing utilities to test your serverless workloads", "author": { "name": "Amazon Web Services", @@ -44,10 +44,10 @@ }, "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/packages/testing#readme", "dependencies": { - "@aws-cdk/cli-lib-alpha": "^2.96.1-alpha.0", + "@aws-cdk/cli-lib-alpha": "^2.107.0-alpha.0", "@aws-sdk/client-lambda": "^3.438.0", "@smithy/util-utf8": "^2.0.0", - "aws-cdk-lib": "^2.96.1", + "aws-cdk-lib": "^2.107.0", "esbuild": "^0.19.3" } } diff --git a/packages/testing/src/constants.ts b/packages/testing/src/constants.ts index e29fbe0132..4cc07ea909 100644 --- a/packages/testing/src/constants.ts +++ b/packages/testing/src/constants.ts @@ -3,7 +3,7 @@ import { Runtime, Architecture } from 'aws-cdk-lib/aws-lambda'; /** * The default AWS Lambda runtime to use when none is provided. */ -const defaultRuntime = 'nodejs18x'; +const defaultRuntime = 'nodejs20x'; /** * The AWS Lambda runtimes that are supported by the project. @@ -11,7 +11,8 @@ const defaultRuntime = 'nodejs18x'; const TEST_RUNTIMES = { nodejs14x: Runtime.NODEJS_14_X, nodejs16x: Runtime.NODEJS_16_X, - [defaultRuntime]: Runtime.NODEJS_18_X, + nodejs18x: Runtime.NODEJS_18_X, + [defaultRuntime]: Runtime.NODEJS_20_X, } as const; /** diff --git a/packages/tracer/CHANGELOG.md b/packages/tracer/CHANGELOG.md index a276714c22..d54bc87cd9 100644 --- a/packages/tracer/CHANGELOG.md +++ b/packages/tracer/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + ## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) **Note:** Version bump only for package @aws-lambda-powertools/tracer diff --git a/packages/tracer/package.json b/packages/tracer/package.json index 8cdc8b6982..59f42282a7 100644 --- a/packages/tracer/package.json +++ b/packages/tracer/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/tracer", - "version": "1.14.2", + "version": "1.15.0", "description": "The tracer package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -16,6 +16,7 @@ "test:e2e:nodejs14x": "RUNTIME=nodejs14x jest --group=e2e", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch", "build": "tsc --build --force", @@ -59,7 +60,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.2", + "@aws-lambda-powertools/commons": "^1.15.0", "aws-xray-sdk-core": "^3.5.3" }, "keywords": [