diff --git a/cdk/WebhookReceiverStack.ts b/cdk/WebhookReceiverStack.ts index 0e018d2e..e60c4925 100644 --- a/cdk/WebhookReceiverStack.ts +++ b/cdk/WebhookReceiverStack.ts @@ -1,16 +1,22 @@ -import * as CDK from 'aws-cdk-lib' -import * as IAM from 'aws-cdk-lib/aws-iam' -import * as Lambda from 'aws-cdk-lib/aws-lambda' -import * as Logs from 'aws-cdk-lib/aws-logs' -import * as SQS from 'aws-cdk-lib/aws-sqs' +import { + App, + CfnOutput, + Duration, + aws_iam as IAM, + aws_lambda as Lambda, + aws_logs as Logs, + RemovalPolicy, + aws_sqs as SQS, + Stack, +} from 'aws-cdk-lib' import { PackedLambda } from './packLambda.js' /** * This is the CloudFormation stack which contains the webhook receiver resources. */ -export class WebhookReceiverStack extends CDK.Stack { +export class WebhookReceiverStack extends Stack { public constructor( - parent: CDK.App, + parent: App, id: string, { lambdaSource, @@ -23,7 +29,7 @@ export class WebhookReceiverStack extends CDK.Stack { // This queue will store all the requests made to the API Gateway const queue = new SQS.Queue(this, 'queue', { fifo: true, - visibilityTimeout: CDK.Duration.seconds(5), + visibilityTimeout: Duration.seconds(5), queueName: `${id}.fifo`, }) @@ -31,10 +37,17 @@ export class WebhookReceiverStack extends CDK.Stack { const lambda = new Lambda.Function(this, 'Lambda', { description: 'Publishes webhook requests into SQS', code: Lambda.Code.fromAsset(lambdaSource.lambdaZipFile), + layers: [ + Lambda.LayerVersion.fromLayerVersionArn( + this, + 'powertool-layer', + `arn:aws:lambda:${Stack.of(this).region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:3`, + ), + ], handler: lambdaSource.handler, runtime: Lambda.Runtime.NODEJS_20_X, architecture: Lambda.Architecture.ARM_64, - timeout: CDK.Duration.seconds(15), + timeout: Duration.seconds(15), initialPolicy: [ new IAM.PolicyStatement({ resources: ['arn:aws:logs:*:*:*'], @@ -56,7 +69,7 @@ export class WebhookReceiverStack extends CDK.Stack { // Create the log group here, so we can control the retention new Logs.LogGroup(this, `LambdaLogGroup`, { - removalPolicy: CDK.RemovalPolicy.DESTROY, + removalPolicy: RemovalPolicy.DESTROY, logGroupName: `/cdk/lambda/${lambda.functionName}`, retention: Logs.RetentionDays.ONE_DAY, }) @@ -66,11 +79,11 @@ export class WebhookReceiverStack extends CDK.Stack { }) // Export these so the test runner can use them - new CDK.CfnOutput(this, 'ApiURL', { + new CfnOutput(this, 'ApiURL', { value: fnUrl.url, exportName: `${this.stackName}:ApiURL`, }) - new CDK.CfnOutput(this, 'QueueURL', { + new CfnOutput(this, 'QueueURL', { value: queue.queueUrl, exportName: `${this.stackName}:QueueURL`, }) diff --git a/lambda/webhookReceiver.ts b/lambda/webhookReceiver.ts index 86bb92f6..3c36c7e6 100644 --- a/lambda/webhookReceiver.ts +++ b/lambda/webhookReceiver.ts @@ -8,8 +8,10 @@ import { APIGatewayProxyEventV2WithRequestContext, APIGatewayProxyResultV2, } from 'aws-lambda' +import { Tracer } from '@aws-lambda-powertools/tracer' -const sqs = new SQSClient({}) +const tracer = new Tracer({}) +const sqs = tracer.captureAWSv3Client(new SQSClient({})) export const handler = async ( event: APIGatewayProxyEventV2WithRequestContext, diff --git a/package-lock.json b/package-lock.json index b84785fe..ff5be9e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0-development", "license": "BSD-3-Clause", "devDependencies": { + "@aws-lambda-powertools/tracer": "2.0.3", "@aws-sdk/client-cloudformation": "3.535.0", "@aws-sdk/client-sqs": "3.535.0", "@aws-sdk/client-xray": "3.535.0", @@ -168,6 +169,30 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/@aws-lambda-powertools/commons": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@aws-lambda-powertools/commons/-/commons-2.0.3.tgz", + "integrity": "sha512-ZuVYhzCkqlMFjAe0mgtNzgIFIJnnd9kZtWO50+YWXhtYK5o9LPHb2drKh8y4mSCIbbaJnbGxMUwas+j1UZl2Uw==", + "dev": true + }, + "node_modules/@aws-lambda-powertools/tracer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@aws-lambda-powertools/tracer/-/tracer-2.0.3.tgz", + "integrity": "sha512-SKuAqTamzAjjH8NzEDurnUgMsgODhAddpt/PlLQdGqkwDfHlFBeaZ6i4VvxbkwQC08/vTv9MBYX6MLtqDnfjxw==", + "dev": true, + "dependencies": { + "@aws-lambda-powertools/commons": "^2.0.3", + "aws-xray-sdk-core": "^3.5.4" + }, + "peerDependencies": { + "@middy/core": ">=3.x" + }, + "peerDependenciesMeta": { + "@middy/core": { + "optional": true + } + } + }, "node_modules/@aws-sdk/client-cloudformation": { "version": "3.535.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.535.0.tgz", @@ -2562,6 +2587,15 @@ "integrity": "sha512-cmmgqxdVGhxYK9lZMYYXYRJk6twBo53ivtXjIUEFZxfxe4TkZTZBK3RRWrY2HjJcUIix0mdifn15yjOAat5lTA==", "dev": true }, + "node_modules/@types/cls-hooked": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.8.tgz", + "integrity": "sha512-tf/7H883gFA6MPlWI15EQtfNZ+oPL0gLKkOlx9UHFrun1fC/FkuyNBpTKq1B5E3T4fbvjId6WifHUdSGsMMuPg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/conventional-commits-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", @@ -3382,6 +3416,24 @@ "node": ">=14" } }, + "node_modules/async-hook-jl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", + "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", + "dev": true, + "dependencies": { + "stack-chain": "^1.3.7" + }, + "engines": { + "node": "^4.7 || >=6.9 || >=7.3" + } + }, + "node_modules/atomic-batcher": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/atomic-batcher/-/atomic-batcher-1.0.2.tgz", + "integrity": "sha512-EFGCRj4kLX1dHv1cDzTk+xbjBFj1GnJDpui52YmEcxxHHEWjYyT6l51U7n6WQ28osZH4S9gSybxe56Vm7vB61Q==", + "dev": true + }, "node_modules/available-typed-arrays": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", @@ -3807,6 +3859,23 @@ "node": ">= 6" } }, + "node_modules/aws-xray-sdk-core": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/aws-xray-sdk-core/-/aws-xray-sdk-core-3.5.4.tgz", + "integrity": "sha512-L4yt2OstsebH8rNAIykDrr+BKjHGxwg5+1FUZAgqDBnaL98sfjPXNYVQNYzg+2ITOjfDbd8NtR1vCQXYVepm+g==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "^3.4.1", + "@smithy/service-error-classification": "^2.0.4", + "@types/cls-hooked": "^4.3.3", + "atomic-batcher": "^1.0.2", + "cls-hooked": "^4.2.2", + "semver": "^7.5.3" + }, + "engines": { + "node": ">= 14.x" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4009,6 +4078,29 @@ "node": ">=0.8.0" } }, + "node_modules/cls-hooked": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", + "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", + "dev": true, + "dependencies": { + "async-hook-jl": "^1.7.6", + "emitter-listener": "^1.0.1", + "semver": "^5.4.1" + }, + "engines": { + "node": "^4.7 || >=6.9 || >=7.3 || >=8.2.1" + } + }, + "node_modules/cls-hooked/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4339,6 +4431,15 @@ "integrity": "sha512-zjqzx4N7xGdl5468G+vcgzDhaHkaYgVcf9MqgexcTqsl2UHSCmOj/Bi3HAprg4BZCpC7HyD8a6nZl6QAZf72gw==", "dev": true }, + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dev": true, + "dependencies": { + "shimmer": "^1.2.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7140,6 +7241,12 @@ "node": ">=8" } }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "dev": true + }, "node_modules/side-channel": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", @@ -7218,6 +7325,12 @@ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, + "node_modules/stack-chain": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", + "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==", + "dev": true + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/package.json b/package.json index 5f8f8222..dcbcd5e7 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "homepage": "https://github.com/NordicSemiconductor/cloud-bdd-markdown-e2e-example-aws-js#readme", "devDependencies": { + "@aws-lambda-powertools/tracer": "2.0.3", "@aws-sdk/client-cloudformation": "3.535.0", "@aws-sdk/client-sqs": "3.535.0", "@aws-sdk/client-xray": "3.535.0",