AWS Lambda での Python コードの作成 - AWS Lambda

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS Lambda での Python コードの作成

Lambda アプリケーションのトレース、デバッグ、および最適化を行うために、Lambda は AWS X-Ray と統合されています。X-Ray を使用すると、Lambda 関数や他の AWS のサービスが含まれるアプリケーション内で、リソースを横断するリクエストをトレースできます。

トレーシングデータを X-Ray に送信するには、以下に表示された 3 つの SDK ライブラリのいずれかを使用できます。

  • AWS Distro for OpenTelemetry (ADOT) – OpenTelemetry (OTel ) SDK の、安全で本番環境に対応した AWSがサポートするディストリビューション。

  • 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 で end-to-end トレースを実装できます。選択方法の詳細については、「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 を使用する

以下の手順に従い、AWS SAM を使用する統合 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 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 -X GET <URL_FROM_PREVIOUS_STEP>

    成功すると、次のレスポンスが表示されます。

    {"message":"hello world"}
  7. 関数のトレースを取得するには、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
  8. これは、インターネット経由でアクセス可能なパブリック 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) モジュールを備えた 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 関数を作成し、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_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 -X GET <URL_FROM_PREVIOUS_STEP>

    成功すると、次のレスポンスが表示されます。

    {"message":"hello world"}
  11. 関数のトレースを取得するには、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
  12. これは、インターネット経由でアクセス可能なパブリック 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 ドキュメントの「Python AWS用 Distro for OpenTelemetry Lambda サポート」を参照してください。

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 関数のアクティブトレースをオンにするには、次のステップに従います。

アクティブトレースをオンにするには
  1. Lambda コンソールの [関数ページ] を開きます。

  2. 関数を選択します。

  3. [設定] を選択してから、[モニタリングおよび運用ツール] を選択します。

  4. [編集] を選択します。

  5. [X-Ray] で、[アクティブトレース] をオンに切り替えます。

  6. [保存] をクリックします。

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 の 2 つの個別のアプリケーションおよびそれぞれに関係するサービスマップを示した図

X-Ray は、アプリケーションへのすべてのリクエストをトレースするわけではありません。X-Ray は、サンプリングアルゴリズムを適用することで効率的なトレースを行うと同時に、すべてのリクエストについての代表的なサンプルを示します。サンプルレートは 1 秒あたり 1 回のリクエストで、追加リクエストの 5% です。

注記

関数の X-Ray サンプルレートは設定することはできません。

アクティブトレースを使用する場合、Lambda はトレースごとに 2 つのセグメントを記録します。これにより、サービスグラフに 2 つのノードが作成されます。次のイメージは、エラープロセッサのサンプルアプリケーションからの主要機能のこれら 2 つのノードを示しています。


      単一の関数を持つ X-Ray サービスマップ。

左に示された 1 つめのノードは、呼び出しリクエストを受信する Lambda サービスを表しています。2 つめのノードは、特定の Lambda 関数を表しています。次の例は、これら 2 つのセグメントを使用したトレースを示しています。いずれも my-function と名付けられていますが、1 つは AWS::Lambda の起点があり、もう 1 つは AWS::Lambda::Function の起点があります。


        特定の Lambda 呼び出しの各サブセグメント間に生じるレイテンシーを示した X-Ray トレースです。

この例では、関数セグメントを展開して、それの 3 つのサブセグメントが表示されています。

  • 初期化 - 関数のロードと初期化コードの実行に要した時間を表します。このサブセグメントは、関数の各インスタンスが処理する最初のイベントに対してのみ表示されます。

  • [呼び出し] - ハンドラーコードの実行に要した時間を表します。

  • [オーバーヘッド] - Lambda ランタイムが次のイベントを処理するための準備に要する時間を表します。

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.8

この設定では、ランタイム依存関係を変更した場合にのみ、ライブラリレイヤーの更新が必要です。関数のデプロイパッケージにはユーザーのコードのみが含まれるため、アップロード時間を短縮できます。

依存関係のレイヤーを作成するには、デプロイ前にレイヤーアーカイブを生成するようにビルドを変更する必要があります。実際の例については、blank-python サンプルアプリケーションを参照してください。