Log and monitor Python Lambda functions - AWS Lambda

Log and monitor Python Lambda functions

AWS Lambda automatically monitors Lambda functions and sends log entries to Amazon CloudWatch. Your Lambda function comes with a CloudWatch Logs log group and a log stream for each instance of your function. The Lambda runtime environment sends details about each invocation and other output from your function's code to the log stream. For more information about CloudWatch Logs, see Using CloudWatch Logs logs with Lambda.

To output logs from your function code, you can use the built-in logging module. For more detailed entries, you can use any logging library that writes to stdout or stderr.

Printing to the log

To send basic output to the logs, you can use a print method in your function. The following example logs the values of the CloudWatch Logs log group and stream, and the event object.

Note that if your function outputs logs using Python print statements, Lambda can only send log outputs to CloudWatch Logs in plain text format. To capture logs in structured JSON, you need to use a supported logging library. See Using Lambda advanced logging controls with Python for more information.

Example lambda_function.py
import os def lambda_handler(event, context): print('## ENVIRONMENT VARIABLES') print(os.environ['AWS_LAMBDA_LOG_GROUP_NAME']) print(os.environ['AWS_LAMBDA_LOG_STREAM_NAME']) print('## EVENT') print(event)
Example log output
START RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95 Version: $LATEST ## ENVIRONMENT VARIABLES /aws/lambda/my-function 2023/08/31/[$LATEST]3893xmpl7fac4485b47bb75b671a283c ## EVENT {'key': 'value'} END RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95 REPORT RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95 Duration: 15.74 ms Billed Duration: 16 ms Memory Size: 128 MB Max Memory Used: 56 MB Init Duration: 130.49 ms XRAY TraceId: 1-5e34a614-10bdxmplf1fb44f07bc535a1 SegmentId: 07f5xmpl2d1f6f85 Sampled: true

The Python runtime logs the START, END, and REPORT lines for each invocation. The REPORT line includes the following data:

REPORT line data fields
  • RequestId – The unique request ID for the invocation.

  • Duration – The amount of time that your function's handler method spent processing the event.

  • Billed Duration – The amount of time billed for the invocation.

  • Memory Size – The amount of memory allocated to the function.

  • Max Memory Used – The amount of memory used by the function. When invocations share an execution environment, Lambda reports the maximum memory used across all invocations. This behavior might result in a higher than expected reported value.

  • Init Duration – For the first request served, the amount of time it took the runtime to load the function and run code outside of the handler method.

  • XRAY TraceId – For traced requests, the AWS X-Ray trace ID.

  • SegmentId – For traced requests, the X-Ray segment ID.

  • Sampled – For traced requests, the sampling result.

Using a logging library

For more detailed logs, use the logging module in the standard library, or any third party logging library that writes to stdout or stderr.

For supported Python runtimes, you can choose whether logs created using the standard logging module are captured in plain text or JSON. To learn more, see Using Lambda advanced logging controls with Python.

Currently, the default log format for all Python runtimes is plain text. The following example shows how log outputs created using the standard logging module are captured in plain text in CloudWatch Logs.

import os import logging logger = logging.getLogger() logger.setLevel("INFO") def lambda_handler(event, context): logger.info('## ENVIRONMENT VARIABLES') logger.info(os.environ['AWS_LAMBDA_LOG_GROUP_NAME']) logger.info(os.environ['AWS_LAMBDA_LOG_STREAM_NAME']) logger.info('## EVENT') logger.info(event)

The output from logger includes the log level, timestamp, and request ID.

START RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125 Version: $LATEST [INFO] 2023-08-31T22:12:58.534Z 1c8df7d3-xmpl-46da-9778-518e6eca8125 ## ENVIRONMENT VARIABLES [INFO] 2023-08-31T22:12:58.534Z 1c8df7d3-xmpl-46da-9778-518e6eca8125 /aws/lambda/my-function [INFO] 2023-08-31T22:12:58.534Z 1c8df7d3-xmpl-46da-9778-518e6eca8125 2023/01/31/[$LATEST]1bbe51xmplb34a2788dbaa7433b0aa4d [INFO] 2023-08-31T22:12:58.535Z 1c8df7d3-xmpl-46da-9778-518e6eca8125 ## EVENT [INFO] 2023-08-31T22:12:58.535Z 1c8df7d3-xmpl-46da-9778-518e6eca8125 {'key': 'value'} END RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125 REPORT RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125 Duration: 2.75 ms Billed Duration: 3 ms Memory Size: 128 MB Max Memory Used: 56 MB Init Duration: 113.51 ms XRAY TraceId: 1-5e34a66a-474xmpl7c2534a87870b4370 SegmentId: 073cxmpl3e442861 Sampled: true
Note

When your function's log format is set to plain text, the default log-level setting for Python runtimes is WARN. This means that Lambda only sends log outputs of level WARN and lower to CloudWatch Logs. To change the default log level, use the Python logging setLevel() method as shown in this example code. If you set your function's log format to JSON, we recommend that you configure your function's log level using Lambda Advanced Logging Controls and not by setting the log level in code. To learn more, see Using log-level filtering with Python

Using Lambda advanced logging controls with Python

To give you more control over how your functions’ logs are captured, processed, and consumed, you can configure the following logging options for supported Lambda Python runtimes:

  • Log format - select between plain text and structured JSON format for your function’s logs

  • Log level - for logs in JSON format, choose the detail level of the logs Lambda sends to Amazon CloudWatch, such as ERROR, DEBUG, or INFO

  • Log group - choose the CloudWatch log group your function sends logs to

For more information about these logging options, and instructions on how to configure your function to use them, see Configuring advanced logging controls for Lambda functions.

To learn more about using the log format and log level options with your Python Lambda functions, see the guidance in the following sections.

Using structured JSON logs with Python

If you select JSON for your function’s log format, Lambda will send logs output by the Python standard logging library to CloudWatch as structured JSON. Each JSON log object contains at least four key value pairs with the following keys:

  • "timestamp" - the time the log message was generated

  • "level" - the log level assigned to the message

  • "message" - the contents of the log message

  • "requestId" - the unique request ID for the function invocation

The Python logging library can also add extra key value pairs such as "logger" to this JSON object.

The examples in the following sections show how log outputs generated using the Python logging library are captured in CloudWatch Logs when you configure your function's log format as JSON.

Note that if you use the print method to produce basic log outputs as described in Printing to the log, Lambda will capture these outputs as plain text, even if you configure your function’s logging format as JSON.

Standard JSON log outputs using Python logging library

The following example code snippet and log output show how standard log outputs generated using the Python logging library are captured in CloudWatch Logs when your function's log format is set to JSON.

Example Python logging code
import logging logger = logging.getLogger() def lambda_handler(event, context): logger.info("Inside the handler function")
Example JSON log record
{ "timestamp":"2023-10-27T19:17:45.586Z", "level":"INFO", "message":"Inside the handler function", "logger": "root", "requestId":"79b4f56e-95b1-4643-9700-2807f4e68189" }

Logging extra parameters in JSON

When your function's log format is set to JSON, you can also log additional parameters with the standard Python logging library by using the extra keyword to pass a Python dictionary to the log output.

Example Python logging code
import logging def lambda_handler(event, context): logging.info( "extra parameters example", extra={"a":"b", "b": [3]}, )
Example JSON log record
{ "timestamp": "2023-11-02T15:26:28Z", "level": "INFO", "message": "extra parameters example", "logger": "root", "requestId": "3dbd5759-65f6-45f8-8d7d-5bdc79a3bd01", "a": "b", "b": [ 3 ] }

Logging exceptions in JSON

The following code snippet shows how Python exceptions are captured in your function's log output when you configure the log format as JSON. Note that log outputs generated using logging.exception are assigned the log level ERROR.

Example Python logging code
import logging def lambda_handler(event, context): try: raise Exception("exception") except: logging.exception("msg")
Example JSON log record
{ "timestamp": "2023-11-02T16:18:57Z", "level": "ERROR", "message": "msg", "logger": "root", "stackTrace": [ " File \"/var/task/lambda_function.py\", line 15, in lambda_handler\n raise Exception(\"exception\")\n" ], "errorType": "Exception", "errorMessage": "exception", "requestId": "3f9d155c-0f09-46b7-bdf1-e91dab220855", "location": "/var/task/lambda_function.py:lambda_handler:17" }

JSON structured logs with other logging tools

If your code already uses another logging library, such as Powertools for AWS Lambda, to produce JSON structured logs, you don’t need to make any changes. AWS Lambda doesn’t double-encode any logs that are already JSON encoded. Even if you configure your function to use the JSON log format, your logging outputs appear in CloudWatch in the JSON structure you define.

The following example shows how log outputs generated using the Powertools for AWS Lambda package are captured in CloudWatch Logs. The format of this log output is the same whether your function’s logging configuration is set to JSON or TEXT. For more information about using Powertools for AWS Lambda, see Using Powertools for AWS Lambda (Python) and AWS SAM for structured logging and Using Powertools for AWS Lambda (Python) and AWS CDK for structured logging

Example Python logging code snippet (using Powertools for AWS Lambda)
from aws_lambda_powertools import Logger logger = Logger() def lambda_handler(event, context): logger.info("Inside the handler function")
Example JSON log record (using Powertools for AWS Lambda)
{ "level": "INFO", "location": "lambda_handler:7", "message": "Inside the handler function", "timestamp": "2023-10-31 22:38:21,010+0000", "service": "service_undefined", "xray_trace_id": "1-654181dc-65c15d6b0fecbdd1531ecb30" }

Using log-level filtering with Python

By configuring log-level filtering, you can choose to send only logs of a certain logging level or lower to CloudWatch Logs. To learn how to configure log-level filtering for your function, see Log-level filtering.

For AWS Lambda to filter your application logs according to their log level, your function must use JSON formatted logs. You can achieve this in two ways:

  • Create log outputs using the standard Python logging library and configure your function to use JSON log formatting. AWS Lambda then filters your log outputs using the “level” key value pair in the JSON object described in Using structured JSON logs with Python. To learn how to configure your function’s log format, see Configuring advanced logging controls for Lambda functions.

  • Use another logging library or method to create JSON structured logs in your code that include a “level” key value pair defining the level of the log output. For example, you can use Powertools for AWS Lambda to generate JSON structured log outputs from your code.

    You can also use a print statement to output a JSON object containing a log level identifier. The following print statement produces a JSON formatted output where the log level is set to INFO. AWS Lambda will send the JSON object to CloudWatch Logs if your function’s logging level is set to INFO, DEBUG, or TRACE.

    print('{"msg":"My log message", "level":"info"}')

For Lambda to filter your function's logs, you must also include a "timestamp" key value pair in your JSON log output. The time must be specified in valid RFC 3339 timestamp format. If you don't supply a valid timestamp, Lambda will assign the log the level INFO and add a timestamp for you.

Viewing logs in Lambda console

You can use the Lambda console to view log output after you invoke a Lambda function.

If your code can be tested from the embedded Code editor, you will find logs in the execution results. When you use the console test feature to invoke a function, you'll find Log output in the Details section.

Viewing logs in CloudWatch console

You can use the Amazon CloudWatch console to view logs for all Lambda function invocations.

To view logs on the CloudWatch console
  1. Open the Log groups page on the CloudWatch console.

  2. Choose the log group for your function (/aws/lambda/your-function-name).

  3. Choose a log stream.

Each log stream corresponds to an instance of your function. A log stream appears when you update your Lambda function, and when additional instances are created to handle multiple concurrent invocations. To find logs for a specific invocation, we recommend instrumenting your function with AWS X-Ray. X-Ray records details about the request and the log stream in the trace.

Viewing logs with AWS CLI

The AWS CLI is an open-source tool that enables you to interact with AWS services using commands in your command line shell. To complete the steps in this section, you must have the following:

You can use the AWS CLI to retrieve logs for an invocation using the --log-type command option. The response contains a LogResult field that contains up to 4 KB of base64-encoded logs from the invocation.

Example retrieve a log ID

The following example shows how to retrieve a log ID from the LogResult field for a function named my-function.

aws lambda invoke --function-name my-function out --log-type Tail

You should see the following output:

{ "StatusCode": 200, "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...", "ExecutedVersion": "$LATEST" }
Example decode the logs

In the same command prompt, use the base64 utility to decode the logs. The following example shows how to retrieve base64-encoded logs for my-function.

aws lambda invoke --function-name my-function out --log-type Tail \ --query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode

The cli-binary-format option is required if you're using AWS CLI version 2. To make this the default setting, run aws configure set cli-binary-format raw-in-base64-out. For more information, see AWS CLI supported global command line options in the AWS Command Line Interface User Guide for Version 2.

You should see the following output:

START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST "AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib", END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Duration: 79.67 ms Billed Duration: 80 ms Memory Size: 128 MB Max Memory Used: 73 MB

The base64 utility is available on Linux, macOS, and Ubuntu on Windows. macOS users may need to use base64 -D.

Example get-logs.sh script

In the same command prompt, use the following script to download the last five log events. The script uses sed to remove quotes from the output file, and sleeps for 15 seconds to allow time for the logs to become available. The output includes the response from Lambda and the output from the get-log-events command.

Copy the contents of the following code sample and save in your Lambda project directory as get-logs.sh.

The cli-binary-format option is required if you're using AWS CLI version 2. To make this the default setting, run aws configure set cli-binary-format raw-in-base64-out. For more information, see AWS CLI supported global command line options in the AWS Command Line Interface User Guide for Version 2.

#!/bin/bash aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out sed -i'' -e 's/"//g' out sleep 15 aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
Example macOS and Linux (only)

In the same command prompt, macOS and Linux users may need to run the following command to ensure the script is executable.

chmod -R 755 get-logs.sh
Example retrieve the last five log events

In the same command prompt, run the following script to get the last five log events.

./get-logs.sh

You should see the following output:

{ "StatusCode": 200, "ExecutedVersion": "$LATEST" } { "events": [ { "timestamp": 1559763003171, "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n", "ingestionTime": 1559763003309 }, { "timestamp": 1559763003173, "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...", "ingestionTime": 1559763018353 }, { "timestamp": 1559763003173, "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r \"key\": \"value\"\r}\n", "ingestionTime": 1559763018353 }, { "timestamp": 1559763003218, "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n", "ingestionTime": 1559763018353 }, { "timestamp": 1559763003218, "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n", "ingestionTime": 1559763018353 } ], "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795", "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080" }

Deleting logs

Log groups aren't deleted automatically when you delete a function. To avoid storing logs indefinitely, delete the log group, or configure a retention period after which logs are deleted automatically.

Using other logging tools and libraries

Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity. The Logger utility provides a Lambda optimized logger which includes additional information about function context across all your functions with output structured as JSON. Use this utility to do the following:

  • Capture key fields from the Lambda context, cold start and structures logging output as JSON

  • Log Lambda invocation events when instructed (disabled by default)

  • Print all the logs only for a percentage of invocations via log sampling (disabled by default)

  • Append additional keys to structured log at any point in time

  • Use a custom log formatter (Bring Your Own Formatter) to output logs in a structure compatible with your organization’s Logging RFC

Using Powertools for AWS Lambda (Python) and AWS SAM for structured logging

Follow the steps below to download, build, and deploy a sample Hello World Python application with integrated Powertools for Python modules using the AWS SAM. This application implements a basic API backend and uses Powertools for emitting logs, metrics, and traces. It consists of an Amazon API Gateway endpoint and a Lambda function. When you send a GET request to the API Gateway endpoint, the Lambda function invokes, sends logs and metrics using Embedded Metric Format to CloudWatch, and sends traces to AWS X-Ray. The function returns a hello world message.

Prerequisites

To complete the steps in this section, you must have the following:

Deploy a sample AWS SAM application
  1. Initialize the application using the Hello World Python template.

    sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.9 --no-tracing
  2. Build the app.

    cd sam-app && sam build
  3. Deploy the app.

    sam deploy --guided
  4. Follow the on-screen prompts. To accept the default options provided in the interactive experience, press Enter.

    Note

    For HelloWorldFunction may not have authorization defined, Is this okay?, make sure to enter y.

  5. Get the URL of the deployed application:

    aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
  6. Invoke the API endpoint:

    curl GET <URL_FROM_PREVIOUS_STEP>

    If successful, you'll see this response:

    {"message":"hello world"}
  7. To get the logs for the function, run sam logs. For more information, see Working with logs in the AWS Serverless Application Model Developer Guide.

    sam logs --stack-name sam-app

    The log output looks like this:

    2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:50.371000 INIT_START Runtime Version: python:3.9.v16 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:07a48df201798d627f2b950f03bb227aab4a655a1d019c3296406f95937e2525 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.112000 START RequestId: d455cfc4-7704-46df-901b-2a5cce9405be Version: $LATEST 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.114000 { "level": "INFO", "location": "hello:23", "message": "Hello world API - HTTP 200", "timestamp": "2023-02-03 14:59:51,113+0000", "service": "PowertoolsHelloWorld", "cold_start": true, "function_name": "sam-app-HelloWorldFunction-YBg8yfYtOc9j", "function_memory_size": "128", "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:sam-app-HelloWorldFunction-YBg8yfYtOc9j", "function_request_id": "d455cfc4-7704-46df-901b-2a5cce9405be", "correlation_id": "e73f8aef-5e07-436e-a30b-63e4b23f0047", "xray_trace_id": "1-63dd2166-434a12c22e1307ff2114f299" } 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.126000 { "_aws": { "Timestamp": 1675436391126, "CloudWatchMetrics": [ { "Namespace": "Powertools", "Dimensions": [ [ "function_name", "service" ] ], "Metrics": [ { "Name": "ColdStart", "Unit": "Count" } ] } ] }, "function_name": "sam-app-HelloWorldFunction-YBg8yfYtOc9j", "service": "PowertoolsHelloWorld", "ColdStart": [ 1.0 ] } 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.126000 { "_aws": { "Timestamp": 1675436391126, "CloudWatchMetrics": [ { "Namespace": "Powertools", "Dimensions": [ [ "service" ] ], "Metrics": [ { "Name": "HelloWorldInvocations", "Unit": "Count" } ] } ] }, "service": "PowertoolsHelloWorld", "HelloWorldInvocations": [ 1.0 ] } 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.128000 END RequestId: d455cfc4-7704-46df-901b-2a5cce9405be 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.128000 REPORT RequestId: d455cfc4-7704-46df-901b-2a5cce9405be Duration: 16.33 ms Billed Duration: 17 ms Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 739.46 ms XRAY TraceId: 1-63dd2166-434a12c22e1307ff2114f299 SegmentId: 3c5d18d735a1ced0 Sampled: true
  8. This is a public API endpoint that is accessible over the internet. We recommend that you delete the endpoint after testing.

    sam delete

Managing log retention

Log groups aren't deleted automatically when you delete a function. To avoid storing logs indefinitely, delete the log group, or configure a retention period after which CloudWatch automatically deletes the logs. To set up log retention, add the following to your AWS SAM template:

Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: # Omitting other properties LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub "/aws/lambda/${HelloWorldFunction}" RetentionInDays: 7

Using Powertools for AWS Lambda (Python) and AWS CDK for structured logging

Follow the steps below to download, build, and deploy a sample Hello World Python application with integrated Powertools for AWS Lambda (Python) modules using the AWS CDK. This application implements a basic API backend and uses Powertools for emitting logs, metrics, and traces. It consists of an Amazon API Gateway endpoint and a Lambda function. When you send a GET request to the API Gateway endpoint, the Lambda function invokes, sends logs and metrics using Embedded Metric Format to CloudWatch, and sends traces to AWS X-Ray. The function returns a hello world message.

Prerequisites

To complete the steps in this section, you must have the following:

Deploy a sample AWS CDK application
  1. Create a project directory for your new application.

    mkdir hello-world cd hello-world
  2. Initialize the app.

    cdk init app --language python
  3. Install the Python dependencies.

    pip install -r requirements.txt
  4. Create a directory lambda_function under the root folder.

    mkdir lambda_function cd lambda_function
  5. Create a file app.py and add the following code to the file. This is the code for the Lambda function.

    from aws_lambda_powertools.event_handler import APIGatewayRestResolver from aws_lambda_powertools.utilities.typing import LambdaContext from aws_lambda_powertools.logging import correlation_paths from aws_lambda_powertools import Logger from aws_lambda_powertools import Tracer from aws_lambda_powertools import Metrics from aws_lambda_powertools.metrics import MetricUnit app = APIGatewayRestResolver() tracer = Tracer() logger = Logger() metrics = Metrics(namespace="PowertoolsSample") @app.get("/hello") @tracer.capture_method def hello(): # adding custom metrics # See: https://docs.powertools.aws.dev/lambda-python/latest/core/metrics/ metrics.add_metric(name="HelloWorldInvocations", unit=MetricUnit.Count, value=1) # structured log # See: https://docs.powertools.aws.dev/lambda-python/latest/core/logger/ logger.info("Hello world API - HTTP 200") return {"message": "hello world"} # Enrich logging with contextual information from Lambda @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) # Adding tracer # See: https://docs.powertools.aws.dev/lambda-python/latest/core/tracer/ @tracer.capture_lambda_handler # ensures metrics are flushed upon request completion/failure and capturing ColdStart metric @metrics.log_metrics(capture_cold_start_metric=True) def lambda_handler(event: dict, context: LambdaContext) -> dict: return app.resolve(event, context)
  6. Open the hello_world directory. You should see a file called hello_world_stack.py.

    cd .. cd hello_world
  7. Open hello_world_stack.py and add the following code to the file. This contains the Lambda Constructor, which creates the Lambda function, configures environment variables for Powertools and sets log retention to one week, and the ApiGatewayv1 Constructor, which creates the REST API.

    from aws_cdk import ( Stack, aws_apigateway as apigwv1, aws_lambda as lambda_, CfnOutput, Duration ) from constructs import Construct class HelloWorldStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Powertools Lambda Layer powertools_layer = lambda_.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", # At the moment we wrote this example, the aws_lambda_python_alpha CDK constructor is in Alpha, o we use layer to make the example simpler # See https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_lambda_python_alpha/README.html # Check all Powertools layers versions here: https://docs.powertools.aws.dev/lambda-python/latest/#lambda-layer layer_version_arn=f"arn:aws:lambda:{self.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:21" ) function = lambda_.Function(self, 'sample-app-lambda', runtime=lambda_.Runtime.PYTHON_3_9, layers=[powertools_layer], code = lambda_.Code.from_asset("./lambda_function/"), handler="app.lambda_handler", memory_size=128, timeout=Duration.seconds(3), architecture=lambda_.Architecture.X86_64, environment={ "POWERTOOLS_SERVICE_NAME": "PowertoolsHelloWorld", "POWERTOOLS_METRICS_NAMESPACE": "PowertoolsSample", "LOG_LEVEL": "INFO" } ) apigw = apigwv1.RestApi(self, "PowertoolsAPI", deploy_options=apigwv1.StageOptions(stage_name="dev")) hello_api = apigw.root.add_resource("hello") hello_api.add_method("GET", apigwv1.LambdaIntegration(function, proxy=True)) CfnOutput(self, "apiUrl", value=f"{apigw.url}hello")
  8. Deploy your application.

    cd .. cdk deploy
  9. Get the URL of the deployed application:

    aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?OutputKey==`apiUrl`].OutputValue' --output text
  10. Invoke the API endpoint:

    curl GET <URL_FROM_PREVIOUS_STEP>

    If successful, you'll see this response:

    {"message":"hello world"}
  11. To get the logs for the function, run sam logs. For more information, see Working with logs in the AWS Serverless Application Model Developer Guide.

    sam logs --stack-name HelloWorldStack

    The log output looks like this:

    2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:50.371000 INIT_START Runtime Version: python:3.9.v16 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:07a48df201798d627f2b950f03bb227aab4a655a1d019c3296406f95937e2525 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.112000 START RequestId: d455cfc4-7704-46df-901b-2a5cce9405be Version: $LATEST 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.114000 { "level": "INFO", "location": "hello:23", "message": "Hello world API - HTTP 200", "timestamp": "2023-02-03 14:59:51,113+0000", "service": "PowertoolsHelloWorld", "cold_start": true, "function_name": "sam-app-HelloWorldFunction-YBg8yfYtOc9j", "function_memory_size": "128", "function_arn": "arn:aws:lambda:us-east-1:111122223333:function:sam-app-HelloWorldFunction-YBg8yfYtOc9j", "function_request_id": "d455cfc4-7704-46df-901b-2a5cce9405be", "correlation_id": "e73f8aef-5e07-436e-a30b-63e4b23f0047", "xray_trace_id": "1-63dd2166-434a12c22e1307ff2114f299" } 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.126000 { "_aws": { "Timestamp": 1675436391126, "CloudWatchMetrics": [ { "Namespace": "Powertools", "Dimensions": [ [ "function_name", "service" ] ], "Metrics": [ { "Name": "ColdStart", "Unit": "Count" } ] } ] }, "function_name": "sam-app-HelloWorldFunction-YBg8yfYtOc9j", "service": "PowertoolsHelloWorld", "ColdStart": [ 1.0 ] } 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.126000 { "_aws": { "Timestamp": 1675436391126, "CloudWatchMetrics": [ { "Namespace": "Powertools", "Dimensions": [ [ "service" ] ], "Metrics": [ { "Name": "HelloWorldInvocations", "Unit": "Count" } ] } ] }, "service": "PowertoolsHelloWorld", "HelloWorldInvocations": [ 1.0 ] } 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.128000 END RequestId: d455cfc4-7704-46df-901b-2a5cce9405be 2023/02/03/[$LATEST]ea9a64ec87294bf6bbc9026c05a01e04 2023-02-03T14:59:51.128000 REPORT RequestId: d455cfc4-7704-46df-901b-2a5cce9405be Duration: 16.33 ms Billed Duration: 17 ms Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 739.46 ms XRAY TraceId: 1-63dd2166-434a12c22e1307ff2114f299 SegmentId: 3c5d18d735a1ced0 Sampled: true
  12. This is a public API endpoint that is accessible over the internet. We recommend that you delete the endpoint after testing.

    cdk destroy