Python Lambda 関数のログ記録とモニタリング - AWS Lambda

Python Lambda 関数のログ記録とモニタリング

AWS Lambda は、Lambda 関数を自動的にモニタリングし、Amazon CloudWatch にログエントリを送信します。Lambda 関数には、関数のインスタンスごとに CloudWatch Logs ロググループとログストリームが用意されています。Lambda のランタイム環境は、各呼び出しの詳細や、関数のコードからのその他の出力をログストリームに送信します。CloudWatch Logs の詳細については、「Lambda で CloudWatch Logs ログを使用する」を参照してください。

関数コードからログを出力するには、組み込み logging モジュールを使用できます。より詳細なエントリを行うため、stdout または stderr に書き込みを行う任意のログ記録ライブラリを使用できます。

ログへの印刷

基本的な出力をログに送信するには、関数の print メソッドを使用できます。次の例では、Amazon CloudWatch Logs のロググループとストリーム、イベントオブジェクトの値をログに記録します。

関数が Python print ステートメントを使用してログを出力する場合、Lambda はログ出力をプレーンテキスト形式でのみ CloudWatch Logs に送信できることに注意してください。構造化 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 ランタイムは、呼び出しごとに STARTEND、および REPORT の各行を記録します。REPORT 行には、次のデータが含まれています。

REPORT 行のデータフィールド
  • RequestId - 呼び出しの一意のリクエスト ID。

  • 所要時間 - 関数のハンドラーメソッドがイベントの処理に要した時間。

  • 課金期間 - 呼び出しの課金対象の時間。

  • メモリサイズ - 関数に割り当てられたメモリの量。

  • 使用中の最大メモリ - 関数によって使用されているメモリの量。呼び出しが実行環境を共有すると、Lambda はすべての呼び出しで使用される最大メモリを報告します。この動作により、予想よりも高い報告値が発生する可能性があります。

  • 初期所要時間 - 最初に処理されたリクエストについて、ハンドラーメソッド外で関数をロードしてコードを実行するためにランタイムにかかった時間。

  • XRAY TraceId - トレースされたリクエストの場合、AWS X-Ray のトレース ID

  • SegmentId - トレースされたリクエストの場合、X-Ray のセグメント ID。

  • サンプリング済み - トレースされたリクエストの場合、サンプリング結果。

ログ記録ライブラリを使用する

より詳細なログのためには、標準ライブラリ内のログ記録モジュール、または stdout や stderr への書き込みを行うサードパーティーのログ記録ライブラリを使用します。

サポートされている Python ランタイムでは、標準 logging モジュールを使用して作成されたログをプレーンテキストまたは JSON のいずれかでキャプチャすることを選択できます。詳細については、「Python での Lambda の高度なログ記録コントロールの使用」を参照してください。

現在、すべての Python ランタイムのデフォルトのログ形式はプレーンテキストです。以下の例は、標準 logging モジュールを使用して作成されたログ出力が 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)

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 は WARN 以下のレベルのログ出力のみを CloudWatch Logs に送信します。デフォルトのログレベルを変更するには、このコード例に示すように Python logging setLevel() メソッドを使用します。関数のログ形式を JSON に設定する場合、コードのログレベルを設定するのではなく、Lambda の高度なログ制御機能を使用して関数のログレベルを設定することをお勧めします。詳細については、「Python でのログレベルフィルタリングの使用」を参照してください。

Python での Lambda の高度なログ記録コントロールの使用

関数のログのキャプチャ、処理、使用方法をより細かく制御するために、サポートされている Lambda Python ランタイムに以下のログ記録オプションを設定できます。

  • ログの形式 - 関数のログをプレーンテキスト形式と構造化された JSON 形式から選択します

  • ログレベル - JSON 形式のログの場合、Lambda が Amazon CloudWatch に送信するログの詳細レベル (ERROR、DEBUG、INFO など) を選択します。

  • ロググループ - 関数がログを送信する CloudWatch ロググループを選択します

これらのログ記録オプションの詳細と、それらのオプションを使用するように関数を設定する方法については、「Lambda 関数の高度なログ記録コントロールの設定」を参照してください。

Python Lambda 関数でのログ形式とログレベルオプションの使用の詳細については、以下のセクションのガイダンスをご覧ください。

Python での構造化された JSON ログの使用

関数のログ形式として JSON を選択した場合、Lambda は Python 標準ログ記録ライブラリによって出力されたログを構造化された JSON として CloudWatch に送信します。各 JSON ログオブジェクトには、以下のキーを含む少なくとも 4 つのキーと値のペアが含まれます。

  • "timestamp" - ログメッセージが生成された時刻

  • "level" - メッセージに割り当てられたログレベル

  • "message" - ログメッセージの内容

  • "requestId" - 関数呼び出しの一意のリクエスト ID

Python logging ライブラリは、この JSON オブジェクトに "logger" などのキーと値のペアを追加することもできます。

以下のセクションの例は、関数のログ形式を JSON として設定したときに、Python logging ライブラリを使用して生成されたログ出力が CloudWatch Logs にどのようにキャプチャされるかを示しています。

ログへの印刷 で説明されているように print メソッドを使用して基本的なログ出力を生成する場合、関数のログ記録形式を JSON として設定した場合でも、Lambda はこれらの出力をプレーンテキストとしてキャプチャすることに注意してください。

Python ログ記録ライブラリを使用した標準 JSON ログ出力

以下のコードスニペットとログ出力例は、関数のログ形式が JSON に設定されている場合、Python logging ライブラリを使用して生成された標準ログ出力が CloudWatch Logs にどのようにキャプチャされるかを示しています。

例 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 に設定されている場合、標準 Python logging ライブラリで extra キーワードを使用して Python ディクショナリをログ出力に渡すことで、追加のパラメータをログに記録することもできます。

例 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 ログ形式を使用するように関数を設定しても、ログ記録出力は定義した JSON 構造で CloudWatch に表示されます。

以下の例は、Powertools for AWS Lambda パッケージを使用して生成されたログ出力が CloudWatch Logs にどのようにキャプチャされるかを示しています。このログ出力の形式は、関数のログ記録設定が 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 Logs に送信するように選択できます。関数にログレベルのフィルタリングを設定する方法については、「ログレベルのフィルタリング」を参照してください。

AWS Lambda でログレベルに従ってアプリケーションログをフィルタリングするには、関数で JSON 形式のログを使用する必要があります。このためには以下の 2 つの方法があります。

  • 標準 Python logging ライブラリを使用してログ出力を作成し、JSON ログフォーマットを使用するように関数を設定します。その後、AWS Lambda は「Python での構造化された JSON ログの使用」で説明されている JSON オブジェクトの「level」キー値のペアを使用してログ出力をフィルタリングします。関数のログ形式を設定する方法については、「Lambda 関数の高度なログ記録コントロールの設定」を参照してください。

  • 別のログ記録ライブラリまたはメソッドを使用して、ログ出力のレベルを定義する「level」キーと値のペアを含む JSON 構造化ログをコード内に作成する。例えば、Powertools for AWS Lambda を使用してコードから JSON 構造化されたログ出力を生成できます。

    print ステートメントを使用して、ログレベル識別子を含む JSON オブジェクトを出力することもできます。以下の print ステートメントは、ログレベルが INFO に設定された JSON 形式の出力を生成します。AWS Lambda は、関数のログ記録レベルが INFO、DEBUG、または TRACE に設定されている場合、JSON オブジェクトを CloudWatch Logs に送信します。

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

Lambda で関数のログをフィルタリングするには、JSON ログ出力に "timestamp" のキーと値のペアも含める必要があります。時間は、有効な RFC 3339 タイムスタンプ形式で指定する必要があります。有効なタイムスタンプを指定しない場合、Lambda はログに INFO レベルを割り当ててタイムスタンプを追加します。

Lambda コンソールでログを表示する

Lambda コンソールを使用して、Lambda 関数を呼び出した後のログ出力を表示できます。

組み込み Code エディタからコードがテスト可能である場合、[実行結果] でログを確認できます。コンソールのテスト機能を使用して関数を呼び出すと、[詳細] セクションで [ログ出力] を確認できます。

CloudWatch コンソールで ログを表示する

Amazon CloudWatch コンソールを使用して、すべての Lambda 関数呼び出しのログを表示できます。

CloudWatch コンソールでログを表示するには
  1. CloudWatch コンソールの [Log groups (ロググループ)] ページを開きます。

  2. 機能のロググループを選択します( /aws/lambda/関数名)

  3. ログストリームを選択します

各ログストリームは、関数のインスタンスに相当します。ログストリームは、Lambda 関数を更新したとき、および複数の同時呼び出しを処理するために追加のインスタンスが作成されたときに表示されます。特定の呼び出しのログを検索するために、AWS X-Ray を使って関数をインストルメント化することをお勧めします。  X-Ray は、リクエストとログストリームの詳細をトレースに記録します。

AWS CLI でログを表示する

AWS CLI は、コマンドラインシェルでコマンドを使用して AWS サービスとやり取りするためのオープンソースツールです。このセクションの手順を完了するには、以下が必要です。

AWS CLI および --log-type コマンドオプションを使用して、呼び出しのログを取得します。レスポンスには、LogResultフィールドが含まれ、このフィールドには、呼び出しから base64 コードされた最大 4 KB のログが含まれます。

例 ログ 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

AWS CLI バージョン 2 を使用している場合、cli-binary-format オプションは必須です。これをデフォルト設定にするには、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、および Windows の Ubuntu で使用できます。macOS ユーザーは、base64 -Dを使用する必要があります 。

例 get-logs.sh スクリプト

同じコマンドプロンプトで、次のスクリプトを使用して、最後の 5 つのログイベントをダウンロードします。このスクリプトはsedを使用して出力ファイルから引用符を削除し、ログが使用可能になるまで15秒待機します。この出力には Lambda からのレスポンスと、get-log-events コマンドからの出力が含まれます。

次のコードサンプルの内容をコピーし、Lambda プロジェクトディレクトリに get-logs.sh として保存します。

AWS CLI バージョン 2 を使用している場合、cli-binary-format オプションは必須です。これをデフォルト設定にするには、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
例 最後の 5 つのログイベントを取得します

同じコマンドプロンプトで、次のスクリプトを実行して、最後の 5 つのログイベントを取得します。

./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 呼び出しイベントをログ記録する (デフォルトでは無効)

  • ログサンプリングにより、特定の割合の呼び出しにのみすべてのログを出力する (デフォルトでは無効)

  • 任意のタイミングで、構造化されたログにキーを追加する

  • カスタムログフォーマッター (Bring Your Own Formatter) を使用して、組織の ログ記録 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 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを 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 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを 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 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