在 AWS Lambda 中检测 Python 代码
Lambda 与 AWS X-Ray 集成,以帮助您跟踪、调试和优化 Lambda 应用程序。您可以在某个请求遍历应用程序中的资源(其中可能包括 Lambda 函数和其他 AWS 服务)时,使用 X-Ray 跟踪该请求。
要将跟踪数据发送到 X-Ray,您可以使用以下三个开发工具包库之一:
-
适用于 OpenTelemetry 的 AWS 发行版 (ADOT)
– 一种安全、可供生产、支持 AWS 的 OpenTelemetry (OTel) SDK 的分发版本。 -
AWS X-Ray SDK for Python – 用于生成跟踪数据并将其发送到 X-Ray 的 SDK
-
Powertools for AWS Lambda(Python)
– 一个开发人员工具包,用于实施无服务器最佳实践并提高开发人员速度。
每个开发工具包均提供了将遥测数据发送到 X-Ray 服务的方法。然后,您可以使用 X-Ray 查看、筛选和获得对应用程序性能指标的洞察,从而发现问题和优化机会。
重要
X-Ray 和 Powertools for AWS Lambda SDK 是 AWS 提供的紧密集成的分析解决方案的一部分。ADOT Lambda Layers 是全行业通用的跟踪分析标准的一部分,该标准通常会收集更多数据,但可能不适用于所有使用案例。您可以使用任一解决方案在 X-Ray 中实现端到端跟踪。要了解有关如何在两者之间进行选择的更多信息,请参阅在 AWS Distro for Open Telemetry 和 X-Ray 开发工具包之间进行选择。
Sections
将 Powertools for AWS Lambda(Python)和 AWS SAM 用于跟踪
请按照以下步骤使用 AWS SAM,通过集成的 Powertools for AWS Lambda(Python)
先决条件
要完成本节中的步骤,您必须满足以下条件:
-
Python 3.11
-
AWS SAM CLI 版本 1.75 或更高版本。如果您使用的是旧版本的 AWS SAM CLI,请参阅升级 AWS SAM CLI。
部署示例 AWS SAM 应用程序
-
使用 Hello World Python 模板初始化该应用程序。
sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.11 --no-tracing
-
构建应用程序。
cd sam-app && sam build
-
部署应用程序。
sam deploy --guided
-
按照屏幕上的提示操作。要在交互式体验中接受提供的默认选项,请按
Enter
。注意
对于 HelloWorldFunction 可能没有定义授权,确定执行此操作吗?,确保输入
y
。 -
获取已部署应用程序的 URL:
aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
-
调用 API 端点:
curl -X GET
<URL_FROM_PREVIOUS_STEP>
如果成功,您将会看到如下响应:
{"message":"hello world"}
-
要获取该函数的跟踪信息,请运行 sam traces。
sam traces
该跟踪输出类似于以下示例:
New XRay Service Graph Start time: 2023-02-03 14:59:50+00:00 End time: 2023-02-03 14:59:50+00:00 Reference Id: 0 - (Root) AWS::Lambda - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [1] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.924 Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.016 Reference Id: 2 - client - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [0] Summary_statistics: - total requests: 0 - ok count(2XX): 0 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0 XRay Event [revision 1] at (2023-02-03T14:59:50.204000) with id (1-63dd2166-434a12c22e1307ff2114f299) and duration (0.924s) - 0.924s - sam-app-HelloWorldFunction-YBg8yfYtOc9j [HTTP: 200] - 0.016s - sam-app-HelloWorldFunction-YBg8yfYtOc9j - 0.739s - Initialization - 0.016s - Invocation - 0.013s - ## lambda_handler - 0.000s - ## app.hello - 0.000s - Overhead
-
这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。
sam delete
X-Ray 无法跟踪对应用程序的所有请求。X-Ray 将应用采样算法确保跟踪有效,同时仍会提供所有请求的一个代表性样本。采样率是每秒 1 个请求和 5% 的其他请求。您无法为函数配置此 X-Ray 采样率。
将 Powertools for AWS Lambda(Python)和 AWS CDK 用于跟踪
请按照以下步骤使用 AWS CDK,通过集成的 Powertools for AWS Lambda(Python)
先决条件
要完成本节中的步骤,您必须满足以下条件:
-
Python 3.11
-
AWS SAM CLI 版本 1.75 或更高版本。如果您使用的是旧版本的 AWS SAM CLI,请参阅升级 AWS SAM CLI。
部署示例 AWS CDK 应用程序
-
为您的新应用程序创建一个项目目录。
mkdir hello-world cd hello-world
-
初始化该应用程序。
cdk init app --language python
-
安装 Python 依赖项。
pip install -r requirements.txt
在根文件夹下创建目录 lambda_function。
mkdir lambda_function cd lambda_function
创建文件 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)
-
打开 hello_world 目录。您应该会看到一个名为 hello_world_stack.py 的文件。
cd .. cd hello_world
打开 hello_world_stack.py,然后将以下代码添加到该文件中。其中包含 Lambda 构造函数,该构造函数可创建 Lambda 函数,为 Powertools 配置环境变量并将日志保留期设置为一周;还包含 ApiGatewayv1 构造函数,用于创建 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_11, 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")
-
部署您的应用程序。
cd .. cdk deploy
-
获取已部署应用程序的 URL:
aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?OutputKey==`apiUrl`].OutputValue' --output text
-
调用 API 端点:
curl -X GET
<URL_FROM_PREVIOUS_STEP>
如果成功,您将会看到如下响应:
{"message":"hello world"}
-
要获取该函数的跟踪信息,请运行 sam traces。
sam traces
该跟踪输出类似于以下示例:
New XRay Service Graph Start time: 2023-02-03 14:59:50+00:00 End time: 2023-02-03 14:59:50+00:00 Reference Id: 0 - (Root) AWS::Lambda - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [1] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.924 Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.016 Reference Id: 2 - client - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [0] Summary_statistics: - total requests: 0 - ok count(2XX): 0 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0 XRay Event [revision 1] at (2023-02-03T14:59:50.204000) with id (1-63dd2166-434a12c22e1307ff2114f299) and duration (0.924s) - 0.924s - sam-app-HelloWorldFunction-YBg8yfYtOc9j [HTTP: 200] - 0.016s - sam-app-HelloWorldFunction-YBg8yfYtOc9j - 0.739s - Initialization - 0.016s - Invocation - 0.013s - ## lambda_handler - 0.000s - ## app.hello - 0.000s - Overhead
-
这是一个可以通过互联网访问的公有 API 端点。我们建议您在测试后删除该端点。
cdk destroy
使用 ADOT 分析您的 Python 函数
ADOT 提供完全托管式 Lambda 层,这些层使用 OTel SDK,将收集遥测数据所需的一切内容打包起来。通过使用此层,您可以在不必修改任何函数代码的情况下,对您的 Lambda 函数进行分析。您还可以将您的层配置为对 OTel 进行自定义初始化。有关更多信息,请参阅 ADOT 文档中的适用于 Lambda 上的 ADOT 收集器的自定义配置
对于 Python 运行时,可以添加 AWS适用于 ADOT Python 的托管 Lambda 层以自动分析您的函数。此层适用于 arm64 和 x86_64 架构。有关如何添加此层的详细说明,请参阅 ADOT 文档中的适用于 OpenTelemetry 的 AWS 发行版对于 Python 的 Lambda 支持
使用 X-Ray SDK 分析您的 Python 函数
要记录有关您的 Lambda 函数对应用程序中的其他资源进行调用的详细信息,您还可以使用 AWS X-Ray SDK for Python。要获取开发工具包,请将 aws-xray-sdk
包添加到应用程序的依赖项中。
例 requirements.txt
jsonpickle==1.3 aws-xray-sdk==2.4.3
在函数代码中,可以通过使用 aws_xray_sdk.core
模块修补 boto3
库来分析 AWS SDK 客户端。
例 函数 – 跟踪 AWS SDK 客户端
import boto3 from aws_xray_sdk.core import xray_recorder from aws_xray_sdk.core import patch_all logger = logging.getLogger() logger.setLevel(logging.INFO) patch_all() client = boto3.client('lambda') client.get_account_settings() def lambda_handler(event, context): logger.info('## ENVIRONMENT VARIABLES\r' + jsonpickle.encode(dict(**os.environ))) ...
在添加正确的依赖项并进行必要的代码更改后,请通过 Lambda 控制台或 API 激活函数配置中的跟踪。
使用 Lambda 控制台激活跟踪
要使用控制台切换 Lambda 函数的活动跟踪,请按照以下步骤操作:
打开活跃跟踪
打开 Lamba 控制台的 Functions
(函数)页面。 -
选择函数。
选择 Configuration(配置),然后选择 Monitoring and operations tools(监控和操作工具)。
选择编辑。
-
在 X-Ray 下方,开启 Active tracing(活动跟踪)。
-
选择保存。
使用 Lambda API 激活跟踪
借助 AWS CLI 或 AWS SDK 在 Lambda 函数上配置跟踪,请使用以下 API 操作:
以下示例 AWS CLI 命令对名为 my-function 的函数启用活跃跟踪。
aws lambda update-function-configuration --function-name my-function \ --tracing-config Mode=Active
跟踪模式是发布函数版本时版本特定配置的一部分。您无法更改已发布版本上的跟踪模式。
使用 AWS CloudFormation 激活跟踪
要对 AWS CloudFormation 模板中的 AWS::Lambda::Function
资源激活跟踪,请使用 TracingConfig
属性。
例 function-inline.yml – 跟踪配置
Resources: function: Type: AWS::Lambda::Function Properties:
TracingConfig: Mode: Active
...
对于 AWS Serverless Application Model (AWS SAM) AWS::Serverless::Function
资源,请使用 Tracing
属性。
例 template.yml – 跟踪配置
Resources: function: Type: AWS::Serverless::Function Properties:
Tracing: Active
...
解释 X-Ray 跟踪
您的函数需要权限才能将跟踪数据上载到 X-Ray。在 Lambda 控制台中激活跟踪后,Lambda 会将所需权限添加到函数的执行角色。如果没有,请将 AWSXRayDaemonWriteAccess
在配置活跃跟踪后,您可以通过应用程序观察特定请求。X-Ray 服务图将显示有关应用程序及其所有组件的信息。以下示例显示了具有两个函数的应用程序。主函数处理事件,有时会返回错误。位于顶部的第二个函数将处理第一个函数的日志组中显示的错误,并使用 AWS SDK 调用 X-Ray、Amazon Simple Storage Service (Amazon S3) 和 Amazon CloudWatch Logs。
X-Ray 无法跟踪对应用程序的所有请求。X-Ray 将应用采样算法确保跟踪有效,同时仍会提供所有请求的一个代表性样本。采样率是每秒 1 个请求和 5% 的其他请求。您无法为函数配置此 X-Ray 采样率。
在 X-Ray 中,跟踪记录有关由一个或多个服务处理的请求的信息。Lambda 会每个跟踪记录 2 个分段,这些分段将在服务图上创建两个节点。下图突出显示了这两个节点:
位于左侧的第一个节点表示接收调用请求的 Lambda 服务。第二个节点表示特定的 Lambda 函数。以下示例显示了一个包含这 2 个分段的跟踪。两者都命名为 my-function,但其中一个函数具有 AWS::Lambda
源,另一个则具有 AWS::Lambda::Function
源。如果 AWS::Lambda
分段显示错误,则表示 Lambda 服务存在问题。如果 AWS::Lambda::Function
分段显示错误,则说明函数存在问题。
此示例将展开 AWS::Lambda::Function
分段,以显示其三个子分段。
注意
AWS 目前正在实施对 Lambda 服务的更改。由于这些更改,您可能会看到 AWS 账户 中不同 Lambda 函数发出的系统日志消息和跟踪分段的结构和内容之间存在细微差异。
此处显示的示例跟踪说明了旧样式函数分段。以下段落介绍了新旧样式分段之间的差异。
这些更改将在未来几周内实施,除中国和 GovCloud 区域外,所有 AWS 区域 的函数都将过渡到使用新格式的日志消息和跟踪分段。
旧样式函数分段包含以下子分段:
-
初始化 – 表示加载函数和运行初始化代码所花费的时间。此子分段仅对由您的函数的每个实例处理的第一个事件显示。
-
调用 – 表示执行处理程序代码花费的时间。
-
开销 – 表示 Lambda 运行时为准备处理下一个事件而花费的时间。
新样式函数分段不包含 Invocation
子分段。而是将客户子分段直接附加到函数分段。有关新旧样式函数分段结构的更多信息,请参阅 了解 X-Ray 跟踪。
您还可以分析 HTTP 客户端、记录 SQL 查询以及使用注释和元数据创建自定义子段。有关更多信息,请参阅 AWS X-Ray 开发人员指南中的 AWS X-Ray SDK for Python。
定价
作为 AWS 免费套餐的组成部分,您可以每月免费使用 X-Ray 跟踪,但不能超过一定限制。超出该阈值后,X-Ray 会对跟踪存储和检索进行收费。有关更多信息,请参阅 AWS X-Ray 定价
在层中存储运行时依赖项 (X-Ray SDK)
如果您使用 X-Ray 开发工具包来分析AWS开发工具包客户端和您的函数代码,则您的部署程序包可能会变得相当大。为了避免每次更新函数代码时上载运行时依赖项,请将 X-Ray SDK 打包到 Lambda 层中。
以下示例显示存储 AWS X-Ray SDK for Python 的 AWS::Serverless::LayerVersion
资源。
例 template.yml – 依赖项层
Resources: function: Type: AWS::Serverless::Function Properties: CodeUri: function/. Tracing: Active
Layers: - !Ref libs
...libs: Type: AWS::Serverless::LayerVersion Properties: LayerName: blank-python-lib Description: Dependencies for the blank-python sample app. ContentUri: package/. CompatibleRuntimes: - python3.11
使用此配置,仅在更改运行时依赖项时您才会更新库层。由于函数部署软件包仅包含您的代码,因此可以帮助缩短上传时间。
为依赖项创建层需要更改构建才能在部署之前生成层存档。有关工作示例,请参阅 blank-python