AWS Lambda での Python コードの作成
Lambda アプリケーションのトレース、デバッグ、および最適化を行うために、Lambda は AWS X-Ray と統合されています。X-Ray を使用すると、Lambda 関数や他の AWS のサービスが含まれるアプリケーション内で、リソースを横断するリクエストをトレースできます。
トレーシングデータを X-Ray に送信するには、以下に表示された 3 つの SDK ライブラリのいずれかを使用できます。
-
AWS Distro for OpenTelemetry (ADOT)
– 安全で本番環境に対応し、AWS でサポートされている OpenTelemetry (OTel) SDK のディストリビューションです。 -
AWS X-Ray SDK for Python - トレースデータを生成して X-Ray に送信するための SDK です。
-
Powertools for AWS Lambda (Python)
- サーバーレスのベストプラクティスを実装し、デベロッパーの作業速度を向上させるためのデベロッパーツールキットです。
各 SDK は、テレメトリデータを X-Ray サービスに送信する方法を提供します。続いて、X-Ray を使用してアプリケーションのパフォーマンスメトリクスの表示やフィルタリングを行い、インサイトを取得することで、問題点や最適化の機会を特定できます。
重要
X-Ray および Powertools for AWS Lambda SDK は、AWS が提供する、密接に統合された計測ソリューションの一部です。ADOT Lambda レイヤーは、一般的により多くのデータを収集するトレーシング計測の業界標準の一部ですが、すべてのユースケースに適しているわけではありません。これらのソリューションのいずれかを使用して、X-Ray でエンドツーエンドのトレーシングを実装することができます。選択方法の詳細については、「Choosing between the AWS Distro for Open Telemetry and X-Ray SDKs」( Distro for Open Telemetry または X-Ray SDK の選択) を参照してください。
セクション
- トレースに Powertools for AWS Lambda (Python) と AWS SAM を使用する
- トレースに Powertools for AWS Lambda (Python) と AWS CDK を使用する
- ADOT を使用して Python 関数をインストルメント化する
- X-Ray SDK を使用して Python 関数をインストルメント化する
- Lambda コンソールを使用してトレースを有効化する
- Lambda API でのトレースのアクティブ化
- AWS CloudFormation によるトレースのアクティブ化
- X-Ray トレースの解釈
- ランタイムの依存関係をレイヤー (X-Ray SDK) に保存する
トレースに 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 秒あたり 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 関数を作成し、Powertools の環境変数を構成し、ログ保持を 1 週間に設定する Lambda コンストラクターと、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_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 は、Otel SDK を使用してテレメトリデータを収集するために必要なすべてをパッケージ化した、フルマネージド型の Lambda レイヤーを提供します。このレイヤーを使用すると、関数コードを変更する必要はなしで、Lambda 関数を計測できます。また、このレイヤーは、OTel でのカスタムな初期化を実行するように構成することもできます。詳細については、ADOT のドキュメントの「Lambda 上での ADOT Collector のカスタム設定
Python ランタイムの場合は、AWS マネージド Lambda layer for ADOT Python を追加して、関数を自動的に計測できます。このレイヤーは、arm64 アーキテクチャと x86_64 アーキテクチャの両方で機能します。このレイヤーの使用方法の詳細については、ADOT のドキュメントの「AWS Distro for OpenTelemetry Lambda Support for Python
X-Ray SDK を使用して Python 関数をインストルメント化する
Lambda 関数がアプリケーション内の他のリソースに対して行う呼び出しの詳細を記録するために、AWS X-Ray SDK for Python を使用することもできます。SDK を取得するには、アプリケーションの依存関係に aws-xray-sdk
パッケージを追加します。
例 requirements.txt
jsonpickle==1.3 aws-xray-sdk==2.4.3
機能コードでは、boto3
ライブラリに aws_xray_sdk.core
モジュールをパッチすることにより、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 関数のアクティブトレースをオンにするには、次のステップに従います。
アクティブトレースをオンにするには
Lambda コンソールの [関数ページ]
を開きます。 -
関数を選択します。
[設定] を選択してから、[モニタリングおよび運用ツール] を選択します。
[編集] を選択します。
-
[X-Ray] で、[アクティブトレース] をオンに切り替えます。
-
[保存] をクリックします。
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 サービスグラフ] には、アプリケーションとそのすべてのコンポーネントに関する情報が表示されます。次の例は、2 つの関数を持つアプリケーションを示しています。プライマリ関数はイベントを処理し、エラーを返す場合があります。上位 2 番目の関数は、最初のロググループに表示されるエラーを処理し、AWS SDKを使用してX-Ray、Amazon Simple Storage Service (Amazon S3)、および Amazon CloudWatch Logs を呼び出します。
X-Ray は、アプリケーションへのすべてのリクエストをトレースするわけではありません。X-Ray は、サンプリングアルゴリズムを適用することで効率的なトレースを行うと同時に、すべてのリクエストについての代表的なサンプルを示します。サンプルレートは 1 秒あたり 1 回のリクエストで、追加リクエストの 5% です。関数の X-Ray サンプルレートを設定することはできません。
X-Ray では、トレースは 1 つ以上のサービスによって処理されるリクエストに関する情報を記録します。Lambda はトレースごとに 2 つのセグメントを記録します。これにより、サービスグラフに 2 つのノードが作成されます。次の図は、これら 2 つのノードを強調表示しています。
左に示された 1 つめのノードは、呼び出しリクエストを受信する Lambda サービスを表しています。2 つめのノードは、特定の Lambda 関数を表しています。次の例は、これら 2 つのセグメントを使用したトレースを示しています。いずれも my-function と名付けられていますが、1 つは AWS::Lambda
の起点があり、もう 1 つは AWS::Lambda::Function
の起点があります。AWS::Lambda
セグメントにエラーが表示される場合は、Lambda サービスに問題があります。AWS::Lambda::Function
セグメントにエラーが表示される場合、関数に問題があります。
この例では、AWS::Lambda::Function
セグメントを展開して、それの 3 つのサブセグメントが表示されています。
注記
AWS は現在、Lambda サービスに変更を実装しています。これらの変更により、AWS アカウント のさまざまな Lambda 関数によって出力されるシステムログメッセージとトレースセグメントの構造と内容にわずかな違いが生じる場合があります。
ここで示すトレースの例は、古いスタイルの関数セグメントを示しています。古いスタイルのセグメントと新しいスタイルのセグメントの違いについては、次の段落で説明します。
これらの変更は今後数週間に実装され、中国および GovCloud リージョンを除くすべての AWS リージョンのすべての関数は、新しい形式のログメッセージとトレースセグメントを使用するように移行されます。
古いスタイルの関数セグメントには、次のサブセグメントが含まれます。
-
初期化 - 関数のロードと初期化コードの実行に要した時間を表します。このサブセグメントは、関数の各インスタンスが処理する最初のイベントに対してのみ表示されます。
-
[呼び出し] - ハンドラーコードの実行に要した時間を表します。
-
[オーバーヘッド] - Lambda ランタイムが次のイベントを処理するための準備に要する時間を表します。
新しいスタイルの関数セグメントには Invocation
サブセグメントが含まれていません。代わりに、顧客サブセグメントが関数セグメントに直接アタッチされます。古いスタイルの関数セグメントと新しいスタイルの関数セグメントの構造の詳細については、「」を参照してくださいX-Ray トレースを理解する。
HTTP クライアントをインストルメント化し、SQL クエリを記録して、注釈とメタデータからカスタムサブセグメントを作成することもできます。詳細については、「AWS X-Ray デベロッパーガイド」の「AWS X-Ray SDK for Python」を参照してください。
料金
X-Ray トレースは、毎月、AWS 無料利用枠で設定された一定限度まで無料で利用できます。X-Ray の利用がこの上限を超えた場合は、トレースによる保存と取得に対する料金が発生します。詳細については、「AWS X-Ray 料金表
ランタイムの依存関係をレイヤー (X-Ray SDK) に保存する
X-Ray SDK を使用して AWS SDK クライアントを関数コードに埋め込むと、デプロイパッケージが巨大になる可能性があります。関数コードを更新するたびにランタイムの依存関係がアップロードされないようにするには、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