From 258d4d5e99474d308d5b5f33ffcbf79422d2824e Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Sat, 16 Dec 2023 19:04:32 -0500 Subject: [PATCH 1/7] add tracing of request events + mention LOG_LEVEL in README --- .../AWSLambdaRuntimeCore/LambdaRunner.swift | 1 + readme.md | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift b/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift index 898fc3e3..0efbcdb8 100644 --- a/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift +++ b/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift @@ -74,6 +74,7 @@ internal final class LambdaRunner { allocator: self.allocator, invocation: invocation ) + logger.trace("Request", metadata: ["bytes": .string(String(buffer: bytes))]) logger.debug("sending invocation to lambda handler") return handler.handle(bytes, context: context) // Hopping back to "our" EventLoop is important in case the handler returns a future that diff --git a/readme.md b/readme.md index 402ac8d1..8baa9057 100644 --- a/readme.md +++ b/readme.md @@ -174,6 +174,45 @@ Next, create a `MyLambda.swift` and implement your Lambda. Note that the file ca Beyond the small cognitive complexity of using the `EventLoopFuture` based APIs, note these APIs should be used with extra care. An `EventLoopLambdaHandler` will execute the user code on the same `EventLoop` (thread) as the library, making processing faster but requiring the user code to never call blocking APIs as it might prevent the underlying process from functioning. +## Testing locally + +Before to deploy your code to AWS Lambda, you can test it locally with the command: + +```sh +LOCAL_LAMBDA_SERVER_ENABLED=true swift run +``` + +This starts a local HTTP endpoint listening on port TCP 7000. Your can invoke your code by sending an HTTP POST command to `http://127.0.0.1:7000/invoke`. + +For example: + +```sh +curl -v --header "Content-Type:\ application/json" --data @events/create-session.json http://127.0.0.1:7000/invoke +* Trying 127.0.0.1:7000... +* Connected to 127.0.0.1 (127.0.0.1) port 7000 +> POST /invoke HTTP/1.1 +> Host: 127.0.0.1:7000 +> User-Agent: curl/8.4.0 +> Accept: */* +> Content-Type:\ application/json +> Content-Length: 1160 +> +< HTTP/1.1 200 OK +< content-length: 247 +< +* Connection #0 to host 127.0.0.1 left intact +{"statusCode":200,"isBase64Encoded":false,"body":"...","headers":{"Access-Control-Allow-Origin":"*","Content-Type":"application\/json; charset=utf-8","Access-Control-Allow-Headers":"*"}} +``` + +## Increase logging verbosity + +You can increase the verbosity of the runtime by changing the LOG_LEVEL environment variable. + +- `LOG_LEVEL=debug` displays information about the Swift AWS Lambda Runtime activity and lifecycle +- `LOG_LEVEL=trace` displays a string representation of the input event as received from the AWS Lambda service (before invoking your handler). + +You can use the `LOG_LEVEL` environment variable both during your local testing (`LOG_LEVEL=trace LOCAL_LAMBDA_SERVER_ENABLED=true swift run`) or when you deploy your code on AWS Lambda. You can define [environment variables for your Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) in the AWS console or programmatically. + ## Deploying to AWS Lambda To deploy Lambda functions to AWS Lambda, you need to compile the code for Amazon Linux which is the OS used on AWS Lambda microVMs, package it as a Zip file, and upload to AWS. From 47beb223fef07d72317b44b24cf03428400b8e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Stormacq?= Date: Mon, 18 Dec 2023 08:20:08 -0500 Subject: [PATCH 2/7] fix typo Co-authored-by: Mahdi Bahrami --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 8baa9057..42f94d1e 100644 --- a/readme.md +++ b/readme.md @@ -174,7 +174,7 @@ Next, create a `MyLambda.swift` and implement your Lambda. Note that the file ca Beyond the small cognitive complexity of using the `EventLoopFuture` based APIs, note these APIs should be used with extra care. An `EventLoopLambdaHandler` will execute the user code on the same `EventLoop` (thread) as the library, making processing faster but requiring the user code to never call blocking APIs as it might prevent the underlying process from functioning. -## Testing locally +## Testing Locally Before to deploy your code to AWS Lambda, you can test it locally with the command: From 123f0a4baa13776e42e403680f83d71109738cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Stormacq?= Date: Mon, 18 Dec 2023 08:22:58 -0500 Subject: [PATCH 3/7] clarify the use of env variable and the swift cli Co-authored-by: Mahdi Bahrami --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 42f94d1e..d083e5d6 100644 --- a/readme.md +++ b/readme.md @@ -176,7 +176,7 @@ Next, create a `MyLambda.swift` and implement your Lambda. Note that the file ca ## Testing Locally -Before to deploy your code to AWS Lambda, you can test it locally with the command: +Before deploying your code to AWS Lambda, you can test it locally by setting the `LOCAL_LAMBDA_SERVER_ENABLED` environment variable to true. It will look like this on CLI: ```sh LOCAL_LAMBDA_SERVER_ENABLED=true swift run From d7fa5a7b9313fbe62bc1d663eb5e85372e88e808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Stormacq?= Date: Mon, 18 Dec 2023 08:23:27 -0500 Subject: [PATCH 4/7] clarify language about HTTP server Co-authored-by: Mahdi Bahrami --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d083e5d6..b121907e 100644 --- a/readme.md +++ b/readme.md @@ -182,7 +182,7 @@ Before deploying your code to AWS Lambda, you can test it locally by setting the LOCAL_LAMBDA_SERVER_ENABLED=true swift run ``` -This starts a local HTTP endpoint listening on port TCP 7000. Your can invoke your code by sending an HTTP POST command to `http://127.0.0.1:7000/invoke`. +This starts a local HTTP server listening on port 7000. You can invoke your local Lambda function by sending an HTTP POST request to `http://127.0.0.1:7000/invoke`. For example: From 252f0837399a3290a81cab30aa71b1df94fe2838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Stormacq?= Date: Mon, 18 Dec 2023 08:29:30 -0500 Subject: [PATCH 5/7] formatting Co-authored-by: Mahdi Bahrami --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index b121907e..2eef4690 100644 --- a/readme.md +++ b/readme.md @@ -206,7 +206,7 @@ curl -v --header "Content-Type:\ application/json" --data @events/create-session ## Increase logging verbosity -You can increase the verbosity of the runtime by changing the LOG_LEVEL environment variable. +You can increase the verbosity of the runtime using the `LOG_LEVEL` environment variable. - `LOG_LEVEL=debug` displays information about the Swift AWS Lambda Runtime activity and lifecycle - `LOG_LEVEL=trace` displays a string representation of the input event as received from the AWS Lambda service (before invoking your handler). From 923092c64673441a3c89557d23fa6e6cb6c67977 Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Mon, 18 Dec 2023 08:46:36 -0500 Subject: [PATCH 6/7] factor in additional suggestions from @mahdibm --- readme.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 2eef4690..5ebf1c35 100644 --- a/readme.md +++ b/readme.md @@ -184,7 +184,9 @@ LOCAL_LAMBDA_SERVER_ENABLED=true swift run This starts a local HTTP server listening on port 7000. You can invoke your local Lambda function by sending an HTTP POST request to `http://127.0.0.1:7000/invoke`. -For example: +The request must include the JSON payload expected as an `Event` by your function. You can create a text file with the JSON payload documented by AWS or captured from a trace. In this example, we used [the APIGatewayv2 JSON payload from the documentation](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html#apigateway-example-event), saved as `events/create-session.json` text file. + +Then we use curl to invoke the local endpoint with the test JSON payload. ```sh curl -v --header "Content-Type:\ application/json" --data @events/create-session.json http://127.0.0.1:7000/invoke @@ -211,7 +213,10 @@ You can increase the verbosity of the runtime using the `LOG_LEVEL` environment - `LOG_LEVEL=debug` displays information about the Swift AWS Lambda Runtime activity and lifecycle - `LOG_LEVEL=trace` displays a string representation of the input event as received from the AWS Lambda service (before invoking your handler). -You can use the `LOG_LEVEL` environment variable both during your local testing (`LOG_LEVEL=trace LOCAL_LAMBDA_SERVER_ENABLED=true swift run`) or when you deploy your code on AWS Lambda. You can define [environment variables for your Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) in the AWS console or programmatically. +You can modify the verbosity of a Lambda function by passing the LOG_LEVEL environment variable both during your local testing (LOG_LEVEL=trace LOCAL_LAMBDA_SERVER_ENABLED=true swift run) or when you deploy your code on AWS Lambda. +You can [define environment variables for your Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) in the AWS console or programmatically. + +This repository follows [Swift's Log Level Guidelines](https://www.swift.org/server/guides/libraries/log-levels.html). At `LOG_LEVEL=trace`, the AWS Lambda runtime will display a string representation of the input event as received from the AWS Lambda service before invoking your handler, for maximum debuggability. ## Deploying to AWS Lambda From abb9f1dfeee6dc8cd9a8bf27c7af226ed8202153 Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Mon, 15 Apr 2024 20:27:28 +0200 Subject: [PATCH 7/7] combine two logger statement into one and print only for Kb of payload --- Sources/AWSLambdaRuntimeCore/LambdaRunner.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift b/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift index b75aae9a..23281b94 100644 --- a/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift +++ b/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift @@ -78,8 +78,13 @@ internal final class LambdaRunner { allocator: self.allocator, invocation: invocation ) - logger.trace("Request", metadata: ["bytes": .string(String(buffer: bytes))]) - logger.debug("sending invocation to lambda handler") + // when log level is trace or lower, print the first Kb of the payload + if logger.logLevel <= .trace, let buffer = bytes.getSlice(at: 0, length: max(bytes.readableBytes, 1024)) { + logger.trace("sending invocation to lambda handler", + metadata: ["1024 first bytes": .string(String(buffer: buffer))]) + } else { + logger.debug("sending invocation to lambda handler") + } return handler.handle(bytes, context: context) // Hopping back to "our" EventLoop is important in case the handler returns a future that // originated from a foreign EventLoop/EventLoopGroup.