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

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

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

関数コードからログを出力するには、「java.lang.System」のメソッドを使用するか、stdout または stderr に書き込む任意のログ記録モジュールを使用できます。

ログを返す関数の作成

関数コードからログを出力するには、java.lang.System のメソッドを使用するか、stdoutstderr に書き込む任意のログ記録モジュールを使用できます。aws-lambda-java-core ライブラリには、コンテキストオブジェクトからアクセスできる LambdaLogger という名前のロガークラスが用意されています。ロガークラスは複数行のログをサポートしています。

以下の例では、コンテキストオブジェクトによって提供される LambdaLogger ロガーを使用しています。

例 Handler.java
// Handler value: example.Handler public class Handler implements RequestHandler<Object, String>{ Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Override public String handleRequest(Object event, Context context) { LambdaLogger logger = context.getLogger(); String response = new String("SUCCESS"); // log execution details logger.log("ENVIRONMENT VARIABLES: " + gson.toJson(System.getenv())); logger.log("CONTEXT: " + gson.toJson(context)); // process event logger.log("EVENT: " + gson.toJson(event)); return response; } }
例 ログの形式
START RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 Version: $LATEST ENVIRONMENT VARIABLES: { "_HANDLER": "example.Handler", "AWS_EXECUTION_ENV": "AWS_Lambda_java8", "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "512", ... } CONTEXT: { "memoryLimit": 512, "awsRequestId": "6bc28136-xmpl-4365-b021-0ce6b2e64ab0", "functionName": "java-console", ... } EVENT: { "records": [ { "messageId": "19dd0b57-xmpl-4ac1-bd88-01bbb068cb78", "receiptHandle": "MessageReceiptHandle", "body": "Hello from SQS!", ... } ] } END RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 REPORT RequestId: 6bc28136-xmpl-4365-b021-0ce6b2e64ab0 Duration: 198.50 ms Billed Duration: 200 ms Memory Size: 512 MB Max Memory Used: 90 MB Init Duration: 524.75 ms

Java ランタイムは、呼び出しごとに STARTEND、および REPORT の各行を記録します。レポート行には、次の詳細が示されます。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Java Lambda 関数でログ形式とログレベルのオプションを使用するには、以下のセクションのガイダンスを参照してください。

Java での構造化された JSON ログ形式の使用

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

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

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

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

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

使用するログ記録方法によっては、JSON 形式でキャプチャされた関数からのログ出力に、追加のキーと値のペアが含まれる場合もあります。

LambdaLogger ロガーを使用して作成するログにレベルを割り当てるには、次の例に示すように、ログコマンドに LogLevel 引数を指定する必要があります。

例 Java ログ記録コード
LambdaLogger logger = context.getLogger(); logger.log("This is a debug log", LogLevel.DEBUG);

このサンプルコードのログ出力は、次のように CloudWatch Logs にキャプチャされます。

例 JSON ログレコード
{ "timestamp":"2023-11-01T00:21:51.358Z", "level":"DEBUG", "message":"This is a debug log", "AWSrequestId":"93f25699-2cbf-4976-8f94-336a0aa98c6f" }

ログ出力にレベルを割り当てない場合、Lambda は自動的に INFO レベルを割り当てます。

コードで既に別のログ記録ライブラリを使用して JSON 構造化ログを作成している場合、変更を加える必要はありません。Lambda は、既に JSON でエンコードされているログを二重エンコードしません。JSON ログ形式を使用するように関数を設定しても、ログ記録出力は定義した JSON 構造で CloudWatch に表示されます。

Java でのログレベルフィルタリングの使用

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

ログレベルのフィルタリングを使用するように関数を設定する場合、Lambda が CloudWatch Logs に送信するログのレベルを以下のオプションから選択する必要があります。

ログレベル 標準的な使用状況
TRACE (最も詳細) コードの実行パスを追跡するために使用される最も詳細な情報
DEBUG システムデバッグの詳細情報
INFO 関数の通常の動作を記録するメッセージ
WARN 対処しないと予期しない動作を引き起こす可能性がある潜在的なエラーに関するメッセージ
ERROR コードが期待どおりに動作しなくなる問題に関するメッセージ
FATAL (詳細度が最も低い) アプリケーションの機能停止を引き起こす重大なエラーに関するメッセージ

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

Lambda は、選択したレベル以下のログを CloudWatch に送信します。例えば、ログレベルを WARN に設定すると、Lambda は WARN、ERROR、FATAL の各レベルに対応するログを送信します。

Log4j2 および SLF4J による高度なログ記録の実装

注記

AWS Lambda では、そのマネージドランタイムとベースコンテナイメージに Log4j2 が含まれていません。このため、これらは CVE-2021-44228、CVE-2021-45046、および CVE-2021-45105 で説明されている問題の影響を受けません。

お客様の関数に影響を受ける Log4j2 バージョンが含まれているという場合のため、CVE-2021-44228、CVE-2021-45046、および CVE-2021-45105 の問題の緩和に役立つ変更を Lambda Java マネージドランタイムベースコンテナイメージに適用しました。この変更の結果、Log4J2 を使用しているお客様には、「Transforming org/apache/logging/log4j/core/lookup/JndiLookup (java.net.URLClassLoader@...)」のような追加のログエントリが表示される場合があります。Log4J2 出力の jndi マッパーを参照するログ文字列は、いずれも「Patched JndiLookup::lookup()」に置き換えられます。

この変更にかかわらず、Log4j2 が含まれる関数を持つすべてのお客様に、最新バージョンへの更新を強くお勧めします。特に、関数で aws-lambda-java-log4j2 ライブラリを使用しているお客様は、バージョン 1.5.0 (またはそれ以降) に更新して、関数を再デプロイするようにしてください。このバージョンは、基盤となる Log4j2 ユーティリティの依存関係をバージョン 2.17.0 (またはそれ以降) に更新します。更新された aws-lambda-java-log4j2 バイナリは Maven リポジトリで、そのソースコードは GitHub で入手できます。

最後に、aws-lambda-java-log4j (v1.0.0 または 1.0.1) に関連するライブラリは、いかなる状況でも使用すべきではないことに注意してください。これらのライブラリは 2015 年にサポートが終了した log4j のバージョン 1.x に関連しています。これらのライブラリはサポートも保守もパッチも適用されておらず、既知のセキュリティの脆弱性があります。

ログ出力をカスタマイズし、ユニットテスト中のログ記録をサポートし、AWS SDK 呼び出しをログに記録するには、SLF4J で Apache Log4j2 を使用します。Log4j は、ログレベルを設定し、アペンダーライブラリを使用できるようにする Java プログラムのログ記録ライブラリです。SLF4J は、関数コードを変更せずに使用するライブラリを切り替えることができるファサードライブラリです。

関数のログにリクエスト ID を追加するには、aws-lambda-java-log4j2 ライブラリのアペンダーを使用します。

src/main/resources/log4j2.xml - アペンダー設定
<Configuration> <Appenders> <Lambda name="Lambda" format="${env:AWS_LAMBDA_LOG_FORMAT:-TEXT}"> <LambdaTextFormat> <PatternLayout> <pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1} - %m%n </pattern> </PatternLayout> </LambdaTextFormat> <LambdaJSONFormat> <JsonTemplateLayout eventTemplateUri="classpath:LambdaLayout.json" /> </LambdaJSONFormat> </Lambda> </Appenders> <Loggers> <Root level="${env:AWS_LAMBDA_LOG_LEVEL:-INFO}"> <AppenderRef ref="Lambda"/> </Root> <Logger name="software.amazon.awssdk" level="WARN" /> <Logger name="software.amazon.awssdk.request" level="DEBUG" /> </Loggers> </Configuration>

Log4j2 ログをプレーンテキスト出力または JSON 出力用に設定する方法は、<LambdaTextFormat> および <LambdaJSONFormat> タグの下にレイアウトを指定することで決定できます。

この例では、テキストモードで、各行の先頭に日付、時刻、リクエスト ID、ログレベル、クラス名が追加されます。JSON モードでは、<JsonTemplateLayout>aws-lambda-java-log4j2 ライブラリに付属する設定で使用されます。

SLF4J は、Java コードでのログ記録のためのファサードライブラリです。関数コードで、SLF4J ロガーファクトリを使用して、info()warn() などのログレベルのメソッドにより、ロガーを取得します。ビルド設定で、ログ記録ライブラリと SLF4J アダプターをクラスパスに含めます。ビルド設定のライブラリを変更することで、関数コードを変更せずにロガータイプを切り替えることができます。SDK for Java からログをキャプチャするには SLF4J が必要です。

以下のサンプルコードでは、ハンドラークラスは SLF4J を使用してロガーを取得しています。

src/main/java/example/HandlerS3.java - SLF4J を使用したログ記録
package example; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; import static org.apache.logging.log4j.CloseableThreadContext.put; public class HandlerS3 implements RequestHandler<S3Event, String>{ private static final Logger logger = LoggerFactory.getLogger(HandlerS3.class); @Override public String handleRequest(S3Event event, Context context) { for(var record : event.getRecords()) { try (var loggingCtx = put("awsRegion", record.getAwsRegion())) { loggingCtx.put("eventName", record.getEventName()); loggingCtx.put("bucket", record.getS3().getBucket().getName()); loggingCtx.put("key", record.getS3().getObject().getKey()); logger.info("Handling s3 event"); } } return "Ok"; } }

このコードにより以下のようなログ出力が生成されます。

例 ログの形式
{ "timestamp": "2023-11-15T16:56:00.815Z", "level": "INFO", "message": "Handling s3 event", "logger": "example.HandlerS3", "AWSRequestId": "0bced576-3936-4e5a-9dcd-db9477b77f97", "awsRegion": "eu-south-1", "bucket": "java-logging-test-input-bucket", "eventName": "ObjectCreated:Put", "key": "test-folder/" }

ビルド設定では、Lambda アペンダーおよび SLF4J アダプターのランタイム依存関係と、Log4j2 の実装依存関係を使用します。

例 build.gradle - 依存関係のログ記録
dependencies { ... 'com.amazonaws:aws-lambda-java-log4j2:[1.6.0,)', 'com.amazonaws:aws-lambda-java-events:[3.11.3,)', 'org.apache.logging.log4j:log4j-layout-template-json:[2.17.1,)', 'org.apache.logging.log4j:log4j-slf4j2-impl:[2.19.0,)', ... }

テスト用にローカルでコードを実行する場合、Lambda ロガーへのアクセスにコンテキストオブジェクトは使用できず、Lambda アペンダーが使用するリクエスト ID はありません。テスト設定の例については、次のセクションのサンプルアプリケーションを参照してください。

他のログ記録ツールとライブラリの使用

Powertools for AWS Lambda (Java) は、サーバーレスのベストプラクティスを実装し、デベロッパーの作業速度を向上させるためのデベロッパーツールキットです。ログ記録ユーティリティには、Lambda に最適化されたロガーを提供し、すべての関数を通して関数コンテキストに関する追加情報が含まれ、JSON 形式で構成した出力を行います。このユーティリティを使用して次のことができます。

  • Lambda の コンテキスト、コールドスタート、構造から主要キーをキャプチャし、JSON 形式でログ出力する

  • 指示された場合 Lambda 呼び出しイベントをログ記録する (デフォルトでは無効)

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

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

  • カスタムログフォーマッター (Bring Your Own Formatter) を使用して、組織の ログ記録 RFC と互換性のある構造でログを出力する

AWS Lambda (Java) に Powertools の使用、構造化されたログ記録に AWS SAM の使用

以下の手順に従い、AWS SAM を使用する統合された Powertools for AWS Lambda (Java) モジュールを備えた Hello World Java アプリケーションのサンプルをダウンロード、構築、デプロイします。このアプリケーションは基本的な API バックエンドを実装し、Powertools を使用してログ、メトリクス、トレースを生成します。Amazon API Gateway エンドポイントと Lambda 関数で構成されています。API Gateway エンドポイントに GET リクエストを送信すると、Lambda 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを CloudWatch に送信、トレースを AWS X-Ray に送信します。関数は hello world のメッセージを返します。

前提条件

このセクションの手順を完了するには、以下が必要です。

AWS SAM サンプルアプリケーションをデプロイする
  1. Hello World Java テンプレートを使用してアプリケーションを初期化します。

    sam init --app-template hello-world-powertools-java --name sam-app --package-type Zip --runtime java11 --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 logs を実行します。詳細については、「AWS Serverless Application Model デベロッパーガイド」の「ログの使用」を参照してください。

    sam logs --stack-name sam-app

    ログ出力は次のようになります。

    2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.095000 INIT_START Runtime Version: java:11.v15 Runtime Version ARN: arn:aws:lambda:eu-central-1::runtime:0a25e3e7a1cc9ce404bc435eeb2ad358d8fa64338e618d0c224fe509403583ca 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.114000 Picked up JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:34.793000 Transforming org/apache/logging/log4j/core/lookup/JndiLookup (lambdainternal.CustomerClassLoader@1a6c5a9e) 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:35.252000 START RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 Version: $LATEST 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.531000 { "_aws": { "Timestamp": 1675416276051, "CloudWatchMetrics": [ { "Namespace": "sam-app-powerools-java", "Metrics": [ { "Name": "ColdStart", "Unit": "Count" } ], "Dimensions": [ [ "Service", "FunctionName" ] ] } ] }, "function_request_id": "7fcf1548-d2d4-41cd-a9a8-6ae47c51f765", "traceId": "Root=1-63dcd2d1-25f90b9d1c753a783547f4dd;Parent=e29684c1be352ce4;Sampled=1", "FunctionName": "sam-app-HelloWorldFunction-y9Iu1FLJJBGD", "functionVersion": "$LATEST", "ColdStart": 1.0, "Service": "service_undefined", "logStreamId": "2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81", "executionEnvironment": "AWS_Lambda_java11" } 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.974000 Feb 03, 2023 9:24:36 AM com.amazonaws.xray.AWSXRayRecorder <init> 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.993000 Feb 03, 2023 9:24:36 AM com.amazonaws.xray.config.DaemonConfiguration <init> 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:36.993000 INFO: Environment variable AWS_XRAY_DAEMON_ADDRESS is set. Emitting to daemon on address XXXX.XXXX.XXXX.XXXX:2000. 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:37.331000 09:24:37.294 [main] INFO helloworld.App - {"version":null,"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-ASN":"16509","CloudFront-Viewer-Country":"IE","Host":"XXXX.execute-api.eu-central-1.amazonaws.com","User-Agent":"curl/7.86.0","Via":"2.0 f0300a9921a99446a44423d996042050.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"t9W5ByT11HaY33NM8YioKECn_4eMpNsOMPfEVRczD7T1RdhbtiwV1Q==","X-Amzn-Trace-Id":"Root=1-63dcd2d1-25f90b9d1c753a783547f4dd","X-Forwarded-For":"XX.XXX.XXX.XX, XX.XXX.XXX.XX","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-ASN":["16509"],"CloudFront-Viewer-Country":["IE"],"Host":["XXXX.execute-api.eu-central-1.amazonaws.com"],"User-Agent":["curl/7.86.0"],"Via":["2.0 f0300a9921a99446a44423d996042050.cloudfront.net (CloudFront)"],"X-Amz-Cf-Id":["t9W5ByT11HaY33NM8YioKECn_4eMpNsOMPfEVRczD7T1RdhbtiwV1Q=="],"X-Amzn-Trace-Id":["Root=1-63dcd2d1-25f90b9d1c753a783547f4dd"],"X-Forwarded-For":["XXX, XXX"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"queryStringParameters":null,"multiValueQueryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"accountId":"XXX","stage":"Prod","resourceId":"at73a1","requestId":"ba09ecd2-acf3-40f6-89af-fad32df67597","operationName":null,"identity":{"cognitoIdentityPoolId":null,"accountId":null,"cognitoIdentityId":null,"caller":null,"apiKey":null,"principalOrgId":null,"sourceIp":"54.240.197.236","cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,"userAgent":"curl/7.86.0","user":null,"accessKey":null},"resourcePath":"/hello","httpMethod":"GET","apiId":"XXX","path":"/Prod/hello/","authorizer":null},"body":null,"isBase64Encoded":false} 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:37.351000 09:24:37.351 [main] INFO helloworld.App - Retrieving https://checkip.amazonaws.com 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.313000 { "function_request_id": "7fcf1548-d2d4-41cd-a9a8-6ae47c51f765", "traceId": "Root=1-63dcd2d1-25f90b9d1c753a783547f4dd;Parent=e29684c1be352ce4;Sampled=1", "xray_trace_id": "1-63dcd2d1-25f90b9d1c753a783547f4dd", "functionVersion": "$LATEST", "Service": "service_undefined", "logStreamId": "2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81", "executionEnvironment": "AWS_Lambda_java11" } 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.371000 END RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 2023/02/03/[$LATEST]851411a899b545eea2cffeba4cfbec81 2023-02-03T09:24:39.371000 REPORT RequestId: 7fcf1548-d2d4-41cd-a9a8-6ae47c51f765 Duration: 4118.98 ms Billed Duration: 4119 ms Memory Size: 512 MB Max Memory Used: 152 MB Init Duration: 1155.47 ms XRAY TraceId: 1-63dcd2d1-25f90b9d1c753a783547f4dd SegmentId: 3a028fee19b895cb 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

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

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

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

CloudWatch コンソールでの ログの表示

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

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

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

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

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

AWS Command Line Interface (AWS CLI) を使用してログを表示する

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

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" }

ログの削除

関数を削除しても、ロググループは自動的には削除されません。ログが無期限に保存されないようにするには、ロググループを削除するか、ログが自動的に削除されるまでの保存期間を設定します。

サンプルログ記録コード

このガイドの GitHub リポジトリには、さまざまなログ記録設定の使用方法を示すサンプルアプリケーションが含まれています。各サンプルアプリケーションには、簡易のデプロイとクリーンアップ用のスクリプト、AWS SAM テンプレート、サポートリソースが含まれています。

Java のサンプル Lambda アプリケーション
  • [java17-examples] — Java レコードを使用して入力イベントデータオブジェクトを表現する方法を示す Java 関数。

  • java-basic - 単位テストと変数ログ記録設定を使用する、最小限の Java 関数のコレクション。

  • java-events - Amazon API Gateway、Amazon SQS、Amazon Kinesis などのさまざまなサービスからのイベントを処理する方法のスケルトンコードを含む Java 関数のコレクション。これらの関数は、最新バージョンの aws-lambda-java-events ライブラリ (3.0.0 以降) を使用します。これらの例では、依存関係としての AWS SDK が不要です。

  • s3-java - Amazon S3 からの通知イベントを処理し、Java Class Library (JCL) を使用して、アップロードされたイメージファイルからサムネイルを作成する Java 関数。

  • custom-serialization – fastJson 、Gson、Moshi、jackson-jr などの一般的なライブラリを使用してカスタムシリアル化を実装する方法例。

  • API Gateway を使用して Lambda 関数を呼び出す - 従業員情報を含む Amazon DynamoDB テーブルをスキャンする Java 関数。次に、Amazon Simple Notification Service を使用して、仕事の記念日を祝うテキストメッセージを従業員に送信します。この例では、API ゲートウェイを使用して関数を呼び出します。

java-basic サンプルアプリケーションは、ログ記録テストをサポートする最小限のログ記録設定を示しています。ハンドラーコードは、コンテキストオブジェクトによって提供される LambdaLogger ロガーを使用します。テストでは、アプリケーションは、Log4j2 ロガーとの LambdaLogger インターフェイスを実装するカスタム TestLogger クラスを使用します。また、AWS SDK との互換性のためのファサードとして SLF4J を使用します。ログ記録ライブラリは、デプロイパッケージを小さく保つために、ビルド出力から除外しています。