メインコンテンツに移動
デベロッパーのためのクラウド活用方法

AWS Lambda Powertools Python入門 第 3 回 ~ Logger Utility

2022-05-02 | Author : 福井 厚

はじめに

皆さん、こんにちは。AWSソリューションアーキテクトの福井です。
第 2 回 では、AWS Lambda Powertools Python の Tracer ユーティリティーの使い方についてご紹介しました。

今回は Core Utilities の中の Logger についてご紹介します。なお、本シリーズでは、AWS Lambda Powertools Python 1.25.1 を対象としています。


X ポスト » | Facebook シェア » | はてブ »

builders.flash メールメンバー登録

builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。
今すぐ登録 »

Logger (Core Utilities)

Logger は JSON で構造化されたアウトプットをログとして提供します。Logger の主な機能は以下の通りです。

  • Lambda コンテキスト、コールドスタートの情報をキャプチャし、JSON で構造化されたログを出力
  • 呼び出された時に Lambda のイベントをロギング (デフォルトでは無効)
  • リクエストのパーセンテージでログのサンプリングを DEBUG ログレベルで有効化可能 (デフォルトは無効)
  • どの時点でも構造化されたログにキーを追加可能

利用方法

AWS Lambda Powertools PythonをLambda関数に組み込む方法については、第 1 回 の記事を参照ください。Logger を利用する際は、以下の 2 つの設定を行います。環境変数でもコンストラクタのパラメータでも設定可能です。

設定

説明

環境変数

コンストラタのパラメータ

ログレベル

どの詳細度の Logger に設定するか (INFO がデフォルト)

LOG_LEVEL

level

サービス

すべてのログストリームに渡って存在するServiceキーを設定

POWERTOOLS_SERVICE_NAME

service

AWS Serverless Application Model (SAM) の例です。(抜粋)

Screenshot showing a YAML configuration example for an AWS Lambda function using AWS::Serverless::Function, with Python 3.9 runtime, x86_64 architecture, and PowerTools environment variables highlighted (LOG_LEVEL: INFO, POWERTOOLS_SERVICE_NAME: logger-demo).

Logger をインポート

Logger を利用するために Logger をインポートしてインスタンス化します。Lambda ハンドラーを含む app.py の先頭でインポートします。

Screenshot of a Python code snippet showing 'from aws_lambda_powertools import Logger' and 'logger = Logger()', illustrating how to import and initialize Logger in AWS Lambda Powertools for Python.

標準の構造化キー

Logger は構造化ログを生成し、以下のキーを含みます。

キー

メモ

level: [str]

INFO

ログのレベル

location:[str]

collect.handler:1

文が実行されたソースコードの場所

message: {Any]

Collecting payment

文字列型にキャストされた JSON の値

timestamp: [str]

2021-05-03 10:20:19, 650+0200

ミリ秒まで含む Timestamp、デフォルトではローカルタイムゾーン を利用

service: [str]

payment

定義されているサービス名

xray_trace_id: [str]

1-5759e988-bd862e3fe1be46a994272793

トレースが有効な場合に X-Ray のトレース ID を表示

sampling_rate: [float]

0.1

有効化されている場合、サンプリングレートをパーセンテージで表示 : 例) 10%

exception_name: [str]

VlueError

例外が発生し、logger.exception が使用された時

exception: [str]

Traceback (most recent call last)...

例外が発生し、logger.exception が使用された時

Lambda コンテキスト情報の取得

inject_lambda_context デコレーター (①) によって、構造化された Lambda コンテキスト情報を含むログを出力することができます。

Screenshot of a Python code example demonstrating use of the Logger utility from AWS Lambda Powertools for logging events and custom keys within an AWS Lambda handler function.

② のログの出力例

② のログは CloudWatch Logs 上で以下のような出力になります。

json
{ 
  "level": "INFO", 
  "location": "lambda_handler:8", 
  "message": "start handler!", 
  "timestamp": "2022-03-25 07:25:54,563+0000", 
  "service": "logger-demo", 
  "cold_start": true, 
  "function_name": "logger-demo-LoggerDemoFunction-xxxxxxxxxxx",
  "function_memory_size": "128",
  "function_arn": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:logger-demo-LoggerDemoFunction-xxxxxxxx", 
  "function_request_id": "9c5a35c7-552d-46f1-a6a5-3a03a5153ff4", 
  "xray_trace_id": "1-623d6e82-6dd0ea50736a04742a5ae904" 
}

③ のログの出力例

同様に、③ のログは CloudWatch Logs 上で以下のような出力になります。

それぞれのログでロケーション情報 (ハンドラー名 : 行番号)、タイムスタンプ、サービス名、コールドスタートが発生したかどうか、Lambda 関数名、Lambda 関数のメモリサイズ、Lambda 関数の ARN、リクエスト ID、X-Ray のトレース ID が含まれる JSON 形式のログが生成されます。

Screenshot showing a JSON log output from AWS Lambda Powertools for Python, highlighting logger_demo operation and custom fields for a builders.flash demo.

入力イベントのロギング

本番環境以外のデバッグ時は、log_event パラメータ、または POWERTOOLS_LOGGER_LOG_EVENT 環境変数の指定で、入力イベントを保存するように Logger を操作することができます。

注意:センシティブな情報が記録されることを防ぐため、この機能はデフォルトでは無効化されています。

Screenshot of Python code using AWS Lambda Powertools, showing a lambda_handler function decorated with @logger.inject_lambda_context(log_event=True) and logging 'start handler!'.

出力ログの例

入力イベントを有効化すると以下のようなログが出力されます。こちらは Amazon API Gateway から Lambda Proxy 統合として呼び出された時の入力イベントの例です。

python
{
    "level": "INFO",
    "location": "decorate:352",
    "message": {
        "resource": "/hello",
        "path": "/hello/",
        "httpMethod": "GET",
        "headers": {
            "Accept": "*/*",
            "CloudFront-Forwarded-Proto": "https",
            "CloudFront-Is-Desktop-Viewer": "true",
            "CloudFront-Is-Mobile-Viewer": "false",
            "CloudFront-Is-SmartTV-Viewer": "false",
            "CloudFront-Is-Tablet-Viewer": "false",
            "CloudFront-Viewer-Country": "JP",
            "Host": "nyuxxno67c.execute-api.us-west-2.amazonaws.com",
            "User-Agent": "curl/7.77.0",
            "Via": "2.0 6c3f41b7aee179237a7e6f3f127xxxxx.cloudfront.net (CloudFront)",
            "X-Amz-Cf-Id": "a4TjfIdP5gHp0bPZq0pfDdZKwGcirxw8rmBIhIRFNwOMII8_NAeZnQ==",
            "X-Amzn-Trace-Id": "Root=1-623d855d-68ad6ddf4dd9d36145490c33",
            "X-Forwarded-For": "27.xxx.xxx.xxx, 130.xxx.xxx.xxx",
            "X-Forwarded-Port": "443",
            "X-Forwarded-Proto": "https"
        },
        "multiValueHeaders": {
            "Accept": [
                "*/*"
            ],
            "CloudFront-Forwarded-Proto": [
                "https"
            ],
            "CloudFront-Is-Desktop-Viewer": [
                "true"
            ],
            "CloudFront-Is-Mobile-Viewer": [
                "false"
            ],
            "CloudFront-Is-SmartTV-Viewer": [
                "false"
            ],
            "CloudFront-Is-Tablet-Viewer": [
                "false"
            ],
            "CloudFront-Viewer-Country": [
                "JP"
            ],
            "Host": [
                "nyuxxno67c.execute-api.us-west-2.amazonaws.com"
            ],
            "User-Agent": [
                "curl/7.77.0"
            ],
            "Via": [
                "2.0 6c3f41b7aee179237a7e6f3f127xxxxx.cloudfront.net (CloudFront)"
            ],
            "X-Amz-Cf-Id": [
                "a4TjfIdP5gHp0bPZq0pfDdZKwGcirxw8rmBIhIRFNwOMII8_NAeZnQ=="
            ],
            "X-Amzn-Trace-Id": [
                "Root=1-623d855d-68ad6ddf4dd9d36145490c33"
            ],
            "X-Forwarded-For": [
                "27.xxx.xxx.xxx, 130.xxx.xxx.xxx"
            ],
            "X-Forwarded-Port": [
                "443"
            ],
            "X-Forwarded-Proto": [
                "https"
            ]
        },
        "queryStringParameters": null,
        "multiValueQueryStringParameters": null,
        "pathParameters": null,
        "stageVariables": null,
        "requestContext": {
            "resourceId": "3or7ty",
            "resourcePath": "/hello",
            "httpMethod": "GET",
            "extendedRequestId": "PiHGrElyPHcF3aA=",
            "requestTime": "25/Mar/2022:09:03:25 +0000",
            "path": "/Prod/hello/",
            "accountId": "786032344772",
            "protocol": "HTTP/1.1",
            "stage": "Prod",
            "domainPrefix": "nyuxxno67c",
            "requestTimeEpoch": 1648199005720,
            "requestId": "47ed9499-5778-405d-a41d-0f02f76cab3f",
            "identity": {
                "cognitoIdentityPoolId": null,
                "accountId": null,
                "cognitoIdentityId": null,
                "caller": null,
                "sourceIp": "27.0.3.153",
                "principalOrgId": null,
                "accessKey": null,
                "cognitoAuthenticationType": null,
                "cognitoAuthenticationProvider": null,
                "userArn": null,
                "userAgent": "curl/7.77.0",
                "user": null
            },
            "domainName": "xxxxxxxxxx.execute-api.us-west-2.amazonaws.com",
            "apiId": "nyuxxno67c"
        },
        "body": null,
        "isBase64Encoded": false
    },
    "timestamp": "2022-03-25 09:03:26,083+0000",
    "service": "logger-demo",
    "cold_start": true,
    "function_name": "logger-demo-LoggerDemoFunction-xxxxxxxxx",
    "function_memory_size": "128",
    "function_arn": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:function:logger-demo-LoggerDemoFunction-xxxxxxxxxx",
    "function_request_id": "734462fd-1faf-41a6-838a-2e1da8c1ebb4",
    "xray_trace_id": "1-623d855d-68ad6ddf4dd9d36145490c33"
}

Correlation ID の設定

Correlation ID の設定

Screenshot of Python code using AWS Lambda Powertools logger, showing the decorator '@logger.inject_lambda_context(correlation_id_path="headers.myapp_status")' and a lambda_handler function that logs the message 'start handler!'.

JMESPath 表現を指定した correlation_id_path パラメータを利用することで、入力イベントの特定の Correlation ID (相関関係 ID) をセットすることができます。設定した Correlation ID は、get_correlation_id メソッドで取得することができます。例えば Amazon API Gateway で公開している API に対してリクエストヘッダにアプリケーション独自のヘッダ情報 (“myapp_status”: “some value” など) を定義している場合、Correlation ID として関連づけるためには以下のように指定します。

CloudWatch Logs

A screenshot showing a JSON log output example from AWS Lambda Powertools for Python, including fields such as level, location, message, timestamp, service, cold_start, function_name, function_memory_size, function_arn, function_request_id, correlation_id, and xray_trace_id.

この結果の CloudWatch Logs の内容は、以下のように correlation_id が追加され、関連付けたヘッダの値が表示されます。

JMESPath 表現

Screenshot of a Python code snippet using AWS Lambda Powertools for logging, showing use of the decorator '@logger.inject_lambda_context' and a basic lambda handler function with a logger.info statement.

Logger Utility では、良く利用されるイベントソースについては組み込みの JMESPath 表現を提供しています。inject_lambda_context デコレーターにこれらの JMESPath 表現を利用することができます。

名前

JMESPath 表現

説明

API_GATEWAY_REST

"requestContext.requestId"

API Gateway REST API request ID

API_GATEWAY_HTTP

"requestContext.requestId"

API Gateway HTTP API request ID

APPSYNC_RESOLVER

'request.headers."x-amzn-trace-id"'

AppSync X-Ray Trace ID

APPLICATION_LOAD_BALANCER

'headers."x-amzn-trace-id"'

ALB X-Ray Trace ID

EVENT_BRIDGE

"id"

EventBridge Event ID

API Gateway REST API request ID

A screenshot showing a JSON log output example from AWS Lambda Powertools for Python, including fields such as level, location, message, timestamp, service, function_name, function_memory_size, function_arn, function_request_id, correlation_id, and xray_trace_id. The correlation_id field is highlighted.

上記のコードを実行すると、CloudWatch Logs には、correlation_id に、API Gateway REST API request ID が設定されます。

新しいキーをログに追加する

2 つの方法

追加のキーを加えるには以下の 2 つの方法があります。

  • append_keys メソッドを使用して将来のすべてのログメッセージに渡って利用するキーを保存
  • extra パラメータを使用してログメッセージ単位にキーを追加する

append_keys メソッド

Screenshot of a Python code snippet demonstrating usage of aws_lambda_powertools Logger within an AWS Lambda handler, including logger.append_keys and logger.info functions.

独自のキーを Logger に追加するために append_keys(**additional_key_value) メソッドを使用します。今回は、GET メソッドのリクエストパラメータとして https://[api_url]/?order_id=0001 のようなクエリ文字列を指定することを想定して、order_id という独自のキーを追加したいと思います。

CloudWatch Logs

A sample JSON log output generated by AWS Lambda Powertools for Python 3.11, showing log level, handler location, service name, message, timestamp, order ID, and X-Ray trace ID.

このコードを実行した結果の CloudWatch Logs ログは、以下のように order_id が追加されます。なお、order_id に値が無い場合は、Logger はキーを追加しません。

extra パラメータ

Screenshot of Python code showing a Lambda handler function using AWS Lambda Powertools Logger with Python 3.12, including adding an extra key with the current time for logging.

extra パラメータは、logger.infologger.warning など、すべてのログレベルメソッドで利用可能です。すべての dictionary を受付け、すべての keyword 引数は構造化ログのルート配下のパーツとして追加されます。extra パラメータでログに追加された keyward 引数は、指定したメッセージにのみ有効で、後続のメッセージには引き継がれません。

CloudWatch Logs

Screenshot of a JSON log output generated by AWS Lambda Powertools for Python, showing an INFO level log event with details such as timestamp, message, service name, handler location, current time, and xray trace ID.

上記のコードを実行した場合の CloudWatch Logs ログは、以下のようになります。

set_correlation_id メソッド

Screenshot of a Python code example using AWS Lambda Powertools for Python 3.14, showing the lambda_handler function with logger.set_correlation_id and logger.info calls to demonstrate structured logging in AWS Lambda.

既存の Logger に文字列値をパラメータに set_correlation_id メソッドを使用して correlation_id を設定することができます。

Data Classes utility

Screenshot of a Python code snippet demonstrating the usage of AWS Lambda Powertools Logger and APIGatewayProxyEvent. The code shows importing necessary modules and setting a correlation ID for API Gateway events in a Lambda function handler.

Data Classes utility を利用して、ドット記述オブジェクトを利用して Logger を設定することもできます。

実行結果

A screenshot showing an example of JSON log output using AWS Lambda Powertools for Python. The log includes fields such as level, location, message, timestamp, service, correlation_id (highlighted), and xray_trace_id.

このコードを実行すると correlation_id に指定した値が設定されて追加されます。

追加したキーの削除

remove_keys メソッド

Screenshot of Python code demonstrating the use of logger in AWS Lambda Powertools to append and remove log keys. The code shows adding a 'sample_key' to the logger and then removing it, with logging statements for both actions.

remove_keys メソッドを使用して追加したキーを削除することができます。

Logging 例外

Screenshot of a Python lambda_handler function illustrating exception handling and logging with logger.exception('Received an exception'), demonstrating Lambda Powertools for Python.

logger.exception メソッドを使用することで、例外に関するコンテキスト情報をロギングすることができます。Logger は、exception_name と exception のキーを含みます。これはトラブルシュートで役立ち、エラーを列挙してくれます。

CloudWatch Logs

A screenshot showing a JSON error log output from AWS Lambda Powertools for Python, highlighting an exception handling example with error level, location, timestamp, service, and traceback details.

上記のコードを実行した場合の CloudWatch Logs ログは、以下のようになります。

Unit Test の実行

Screenshot of a Python code example showing how to mock the Lambda context object for unit testing using Lambda Powertools, with highlighted sections for the LambdaContext dataclass and usage in a test function.

inject_lambda_context デコレーターを利用したハンドラに対して Unit Test を実行する時は、ダミーの Lambda Context を渡す必要があります。そうしないと Logger の実行が失敗します。次の pytest のサンプルは Logger が成功するために必要な、最小限の Lambda Context 情報を渡してます。(Python の dataclasses は Python 3.7 以降でのみ利用可能です。)

まとめ

今回は、AWS Lambda Powertools Python の Logger について紹介しました。Logger を利用することで構造化されたログを簡単に追加できることがお分かり頂けたと思います。また Lambda Context 情報のログへの書き込み、correlation ID の指定、Logger のキーの追加、削除が簡単に行えることも紹介しました。

皆様の Lambda 関数に AWS Lambda Powertools Python を組み込んでご活用ください。
次回は Metrics を紹介します。どうぞお楽しみに。

筆者プロフィール


福井 厚

アマゾン ウェブ サービス ジャパン合同会社
シニアソリューションアーキテクト サーバーレススペシャリスト

2015 年からアマゾンウェブサービスジャパンでソリューションアーキテクトとして活動。サーバーレススペシャリストとして日々モダンアプリケーション開発とサーバーレスの活用の技術支援を行なっています。

A portrait photograph of a smiling man wearing glasses, a beard, and a red sweater over a pink shirt. The image is titled 'Portrait of Fukui Atsushi, 2021.'