Python 中的 AWS Lambda 函数日志记录 - AWS Lambda

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Python 中的 AWS Lambda 函数日志记录

AWS Lambda自动监控 Lambda 函数并将日志条目发送到亚马逊。 CloudWatch您的 Lambda 函数带有 CloudWatch 日志日志组和每个函数实例的日志流。Lambda 运行时系统环境会将每次调用的详细信息以及函数代码的其他输出发送到该日志流。有关 CloudWatch 日志的更多信息,请参阅将 Amazon CloudWatch 日志与 AWS Lambda

要从函数代码输出日志,可以使用内置的 logging 模块。如需更详细的条目,可以使用任何写入 stdout 或 stderr 的日志记录库。

输出到日志

要将基本输出发送到日志,您可以使用函数中的 print 方法。以下示例记录了 Lo CloudWatch gs 日志组和流的值以及事件对象。

请注意,如果您的函数使用 Python print 语句输出日志,则 Lambda 只能以纯文本格式将 CloudWatch 日志输出发送到日志。要以结构化的 JSON 格式捕获日志,需要使用支持的日志记录库。请参阅在 Python 中使用 Lambda 高级日志记录控件了解更多信息。

例 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)
例 日志输出
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

Python 运行时记录每次调用的 STARTENDREPORT 行。REPORT 行包括以下数据:

REPORT 行数据字段
  • RequestId— 调用的唯一请求 ID。

  • Duration(持续时间)– 函数的处理程序方法处理事件所花费的时间。

  • Billed Duration(计费持续时间)– 针对调用计费的时间量。

  • Memory Size(内存大小)– 分配给函数的内存量。

  • Max Memory Used(最大内存使用量)– 函数使用的内存量。

  • Init Duration(初始持续时间)– 对于提供的第一个请求,为运行时在处理程序方法外部加载函数和运行代码所花费的时间。

  • XRAY TraceId — 对于已跟踪的请求,为AWS X-Ray跟踪 ID。

  • SegmentId— 对于已跟踪的请求,使用 X-Ray 分段 ID。

  • Sampled(采样)– 对于追踪的请求,为采样结果。

使用日志记录库

如需更详细的日志,请使用标准库中的日志记录模块,或任何写入 stdout 或 stderr 的第三方日志记录库。

对于支持的 Python 运行时系统,您可以选择以纯文本还是 JSON 格式捕获使用标准 logging 模块创建的日志。要了解更多信息,请参阅在 Python 中使用 Lambda 高级日志记录控件

目前,所有 Python 运行时的默认日志格式均为纯文本。以下示例显示了如何在日志中以纯文本形式捕获使用标准logging模块创建的 CloudWatch 日志输出。

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)

logger 的输出包括日志级别、时间戳和请求 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
注意

当函数的日志格式设置为纯文本时,Python 运行时系统的默认日志级别设置为 WARN。这意味着 Lambda 仅向 Logs 发送级别为 CloudWatch WARN 及以下级别的日志输出。要更改默认日志级别,请使用 Python logging setLevel() 方法,如本示例代码所示。如果将函数的日志格式设置为 JSON,则建议使用 Lambda 高级日志记录控件来配置函数的日志级别,而不是通过在代码中设置日志级别。要了解更多信息,请参阅 在 Python 中使用日志级别筛选

在 Python 中使用 Lambda 高级日志记录控件

为了让您更好地控制如何捕获、处理和使用函数日志,您可以为支持的 Lambda Python 运行时系统配置以下日志记录选项:

  • 日志格式 - 为函数日志选择纯文本或结构化的 JSON 格式

  • 日志级别-对于 JSON 格式的日志,选择 Lambda 发送给 Amazon 的日志的详细级别 CloudWatch,例如错误、调试或信息

  • 日志组-选择您的函数将 CloudWatch 日志发送到的日志组

有关这些日志记录选项的更多信息以及如何通过配置来使用函数的说明,请参阅 为您的 Lambda 函数配置高级日志记录控件

要详细了解如何在 Python Lambda 函数中使用日志格式和日志级别选项,请参阅以下各节中的指南。

在 Python 中使用结构化的 JSON 日志

如果您为函数的日志格式选择 JSON,Lambda 会将 Python 标准日志库输出的日志 CloudWatch 作为结构化 JSON 发送到结构化的 JSON。每个 JSON 日志对象包含至少四个键值对和以下键:

  • "timestamp" - 生成日志消息的时间

  • "level" - 分配给消息的日志级别

  • "message" - 日志消息的内容

  • "requestId" - 函数调用的唯一请求 ID

Python logging 库还可以向此 JSON 对象添加其他键值对,例如 "logger"

以下各节中的示例显示了当您将函数的日志格式配置为 JSON 时,如何在 Lo CloudWatch gs 中捕获使用 Python logging 库生成的日志输出。

请注意,如果您使用 print 方法生成基本日志输出(如 输出到日志 中所述),则即使您将函数的日志格式配置为 JSON,Lambda 也会将这些输出捕获为纯文本。

使用 Python 日志记录库的标准 JSON 日志输出

以下示例代码段和日志输出显示了当您的函数的日志格式设置为 JSON 时,如何在 Lo CloudWatch gs 中捕获使用 Python logging 库生成的标准日志输出。

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

在 JSON 中记录额外的参数

将函数的日志格式设置为 JSON 时,您还可以使用extra关键字将 Python 字典传递给日志输出,从而使用标准 Python logging 库记录其他参数。

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

在 JSON 中记录异常

以下代码段显示了当您将日志格式配置为 JSON 时,如何在函数的日志输出中捕获 Python 异常。请注意,使用 logging.exception 生成的日志输出被分配了日志级别 ERROR。

例 Python 日志记录代码
import logging def lambda_handler(event, context): try: raise Exception("exception") except: logging.exception("msg")
例 JSON 日志记录
{ "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 结构化日志

如果您的代码已经使用其他日志记录库(例如 Powertools for AWS Lambda)来生成 JSON 结构化日志,则无需进行任何更改。AWS Lambda 不会对任何已采用 JSON 编码的日志进行双重编码。即使您将函数配置为使用 JSON 日志格式,您的日志输出也会显示 CloudWatch 在您定义的 JSON 结构中。

以下示例显示了如何在日志中捕获使用 Powertools for AWS Lambda 软件包生成的 CloudWatch 日志输出。无论您的函数的日志配置设置为 JSON 还是 TEXT,此日志输出的格式都相同。有关使用 Powertools for AWS Lambda 的更多信息,请参阅 将 Powertools for AWS Lambda(Python)和 AWS SAM 用于结构化日志记录将 Powertools for AWS Lambda(Python)和 AWS CDK 用于结构化日志记录

例 Python 日志记录代码段(使用 Powertools for AWS Lambda)
from aws_lambda_powertools import Logger logger = Logger() def lambda_handler(event, context): logger.info("Inside the handler function")
例 JSON 日志记录(使用 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" }

在 Python 中使用日志级别筛选

通过配置日志级别筛选,您可以选择仅将特定日志级别或更低级别的日志发送到 CloudWatch 日志。要了解如何为您的函数配置日志级别筛选,请参阅 日志级别筛选

为了让 AWS Lambda 根据日志级别筛选应用程序日志,您的函数必须使用 JSON 格式的日志。您可以通过两种方式实现这一点:

  • 使用标准 Python logging 库创建日志输出,并将您的函数配置为使用 JSON 日志格式。然后 AWS Lambda 会使用 在 Python 中使用结构化的 JSON 日志 中所述的 JSON 对象中的“级别”键值对筛选日志输出。要了解如何配置函数的日志格式,请参阅 为您的 Lambda 函数配置高级日志记录控件

  • 使用其他日志记录库或方法在代码中创建 JSON 结构化日志,其中包含定义日志输出级别的“级别”键值对。例如,您可以使用 Powertools for AWS Lambda 通过代码生成 JSON 结构化日志输出。

    您也可以使用 print 语句输出包含日志级别标识符的 JSON 对象。以下 print 语句生成 JSON 格式的输出,其中日志级别设置为 INFO。 AWS Lambda如果您的函数的 CloudWatch 日志级别设置为 INFO、DEBUG 或 TRACE,则会将 JSON 对象发送到日志。

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

要让 Lambda 筛选函数的日志,还必须在 JSON 日志输出中包含一个 "timestamp" 键值对。必须以有效的 RFC 3339 时间戳格式指定时间。如果您未提供有效的时间戳,Lambda 将为日志分配 INFO 级别并为您添加时间戳。

在 Lambda 控制台中查看日志

调用 Lambda 函数后,您可以使用 Lambda 控制台查看日志输出。

如果可以在嵌入式代码编辑器中测试代码,则可以在执行结果中找到日志。使用控制台测试功能调用函数时,可以在详细信息部分找到日志输出

在 CloudWatch 控制台中查看日志

您可以使用亚马逊 CloudWatch 控制台查看所有 Lambda 函数调用的日志。

在 CloudWatch 控制台上查看日志
  1. 在 CloudWatch 控制台上打开日志组页面

  2. 为您的函数选择日志组 (/aws/lambda/ your-function-name)。

  3. 创建日志流。

每个日志流对应一个函数实例。日志流会在您更新 Lambda 函数以及创建更多实例来处理多个并发调用时显示。要查找特定调用的日志,建议您使用 AWS X-Ray 检测函数。X-Ray 会在追踪中记录有关请求和日志流的详细信息。

如需使用将日志和跟踪与 X-Ray 相关联的示例应用程序,请参阅 AWS Lambda 错误处理器示例应用程序

使用 AWS CLI  查看日志

AWS CLI 是一种开源工具,让您能够在命令行 Shell 中使用命令与 AWS 服务进行交互。要完成本节中的步骤,您必须满足以下条件:

您可以通过 AWS CLI,使用 --log-type 命令选项检索调用的日志。响应包含一个 LogResult 字段,其中包含多达 4KB 来自调用的 base64 编码日志。

例 检索日志 ID

以下示例说明如何从 LogResult 字段中检索名为 my-function 的函数的日志 ID

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

您应看到以下输出:

{ "StatusCode": 200, "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...", "ExecutedVersion": "$LATEST" }
例 解码日志

在同一命令提示符下,使用 base64 实用程序解码日志。以下示例说明如何为 my-function 检索 base64 编码的日志。

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

如果使用 cli-binary-format 版本 2,则 AWS CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 AWS Command Line Interface 用户指南中的 AWS CLI 支持的全局命令行选项

您应看到以下输出:

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

base64 实用程序在 Linux、macOS 和 Ubuntu on Windows 上可用。macOS 用户可能需要使用 base64 -D

例 get-logs.sh 脚本

在同一命令提示符下,使用以下脚本下载最后五个日志事件。此脚本使用 sed 从输出文件中删除引号,并休眠 15 秒以等待日志可用。输出包括来自 Lambda 的响应,以及来自 get-log-events 命令的输出。

复制以下代码示例的内容并将其作为 get-logs.sh 保存在 Lambda 项目目录中。

如果使用 cli-binary-format 版本 2,则 AWS CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 AWS Command Line Interface 用户指南中的 AWS CLI 支持的全局命令行选项

#!/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
例 macOS 和 Linux(仅限)

在同一命令提示符下,macOS 和 Linux 用户可能需要运行以下命令以确保脚本可执行。

chmod -R 755 get-logs.sh
例 检索最后五个日志事件

在同一命令提示符下,运行以下脚本以获取最后五个日志事件。

./get-logs.sh

您应看到以下输出:

{ "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" }

删除日志

删除函数时,日志组不会自动删除。要避免无限期存储日志,请删除日志组,或配置一个保留期,在该保留期之后,日志将自动删除。

工具和库

Powertools for AWS Lambda(Python)是一个开发人员工具包,用于实施无服务器最佳实践并提高开发人员速度。日志记录实用程序提供经优化的 Lambda 日志记录程序,其中包含有关所有函数的函数上下文的附加信息,输出结构为 JSON。请使用该实用程序执行以下操作:

  • 从 Lambda 上下文中捕获关键字段,冷启动并将日志记录输出结构化为 JSON

  • 根据指示记录 Lambda 调用事件(默认情况下禁用)

  • 通过日志采样仅针对一定百分比的调用输出所有日志(默认情况下禁用)

  • 在任何时间点将其他键附加到结构化日志

  • 使用自定义日志格式设置程序(自带格式设置程序),从而在与组织的日志记录 RFC 兼容的结构中输出日志

将 Powertools for AWS Lambda(Python)和 AWS SAM 用于结构化日志记录

请按照以下步骤使用 AWS SAM,通过集成的 Powertools for Python 模块来下载、构建和部署示例 Hello World Python 应用程序。此应用程序实现了基本的 API 后端,并使用 Powertools 发送日志、指标和跟踪。它由 Amazon API Gateway 端点和 Lambda 函数组成。当您向 API Gateway 终端节点发送 GET 请求时,Lambda 函数会调用、使用嵌入式指标格式向其发送日志和指标 CloudWatch,并将跟踪发送到。AWS X-Ray该函数将返回一条 hello world 消息。

先决条件

要完成本节中的步骤,您必须满足以下条件:

部署示例 AWS SAM 应用程序
  1. 使用 Hello World Python 模板初始化该应用程序。

    sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.9 --no-tracing
  2. 构建应用程序。

    cd sam-app && sam build
  3. 部署应用程序。

    sam deploy --guided
  4. 按照屏幕上的提示操作。要在交互式体验中接受提供的默认选项,请按 Enter

    注意

    因为HelloWorldFunction 可能没有定义授权,这样可以吗? ,请务必输入y

  5. 获取已部署应用程序的 URL:

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

    curl GET <URL_FROM_PREVIOUS_STEP>

    如果成功,您将会看到如下响应:

    {"message":"hello world"}
  7. 要获取该函数的日志,请运行 sam logs。有关更多信息,请参阅《AWS Serverless Application Model 开发人员指南》中的 使用日志

    sam logs --stack-name sam-app

    该日志输出类似于以下示例:

    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. 这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。

    sam delete

管理日志保留日期

删除函数时,日志组不会自动删除。为避免无限期存储日志,请删除该日志组,或配置保留期,之后 CloudWatch 自动删除日志。要设置日志保留日期,请将以下内容添加到您的 AWS SAM 模板中:

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

将 Powertools for AWS Lambda(Python)和 AWS CDK 用于结构化日志记录

请按照以下步骤使用 AWS CDK,通过集成的 Powertools for AWS Lambda(Python)模块来下载、构建和部署示例 Hello World Python 应用程序。此应用程序实现了基本的 API 后端,并使用 Powertools 发送日志、指标和跟踪。它由 Amazon API Gateway 端点和 Lambda 函数组成。当您向 API Gateway 终端节点发送 GET 请求时,Lambda 函数会调用、使用嵌入式指标格式向其发送日志和指标 CloudWatch,并将跟踪发送到。AWS X-Ray该函数将返回一条 hello world 消息。

先决条件

要完成本节中的步骤,您必须满足以下条件:

部署示例 AWS CDK 应用程序
  1. 为您的新应用程序创建一个项目目录。

    mkdir hello-world cd hello-world
  2. 初始化该应用程序。

    cdk init app --language python
  3. 安装 Python 依赖项。

    pip install -r requirements.txt
  4. 在根文件夹下创建目录 lambda_function

    mkdir lambda_function cd lambda_function
  5. 创建文件 app.py 并将以下代码添加到该文件中。这是适用于 Lambda 函数的代码。

    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. 打开 hello_world 目录。您应该会看到一个名为 hello_world_stack.py 的文件。

    cd .. cd hello_world
  7. 打开 hello_world_stack.py,然后将以下代码添加到该文件中。它包含 Lambda 构造函数,它创建 Lambda 函数,为 Powertools 配置环境变量并将日志保留时间设置为一周,以及创建 REST API 的 ApiGatewayv1 构造函数

    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. 部署您的应用程序。

    cd .. cdk deploy
  9. 获取已部署应用程序的 URL:

    aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?OutputKey==`apiUrl`].OutputValue' --output text
  10. 调用 API 端点:

    curl GET <URL_FROM_PREVIOUS_STEP>

    如果成功,您将会看到如下响应:

    {"message":"hello world"}
  11. 要获取该函数的日志,请运行 sam logs。有关更多信息,请参阅《AWS Serverless Application Model 开发人员指南》中的 使用日志

    sam logs --stack-name HelloWorldStack

    该日志输出类似于以下示例:

    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. 这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。

    cdk destroy