記錄和監控 Java Lambda 函數 - AWS Lambda

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

記錄和監控 Java Lambda 函數

AWS Lambda 會自動監控 Lambda 函數,並將日誌項目傳送至 Amazon CloudWatch。您的 Lambda 函數隨附有 CloudWatch Logs 日誌群組,且函數的每一執行個體各有一個日誌串流。Lambda 執行期環境會將每次調用的詳細資訊和函數程式碼的其他輸出,傳送至日誌串流。如需 CloudWatch Logs 的詳細資訊,請參閱將 CloudWatch Logs 與 Lambda 搭配使用

若要由您的函數程式碼輸出日誌,可以使用 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 執行時間會記錄每次調用的 STARTENDREPORT 行。報告明細行提供下列詳細資訊:

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 會以結構化 JSON 形式使用 LambdaLogger 類別傳送日誌輸出。每個 JSON 日誌物件都包含至少四個鍵值對,其中包含下列索引鍵:

  • "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 格式的日誌。您可以透過兩種方式達成此操作:

將函數設定為使用日誌層級篩選時,您必須從下列選項中選取要 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 版本的情況,我們已將變更套用至 Lambda Java 受管執行時間基礎容器映像,這有助於緩解 CVE-2021-44228、CVE-2021-45046 和 CVE-2021-45105 中的問題。由於此變更,使用 Log4J2 的客戶可能會看到一個額外的日誌條目,類似於「Transforming org/apache/logging/log4j/core/lookup/JndiLookup (java.net.URLClassLoader@...)」。在 Log4J2 輸出中參考 jndi 映射器的任何日誌字串都將替換為「Patched JndiLookup::lookup()」。

除此變更之外,我們強烈建議其函數包含 Log4j2 的所有客戶將 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 or 1.0.1) 相關的任何程式庫。這些程式庫與 log4j 的 第 1.x 版本相關,該版本已於 2015 年停止使用。這些程式庫不受支援、未受維護、未經修補,且具有已知的安全性漏洞。

若要自訂日誌輸出、在單元測試期間支援日誌記錄,以及記錄 AWS 開發套件呼叫,請使用 Apache Log4j2 搭配 SLF4J。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>

您可以透過在 <LambdaTextFormat><LambdaJSONFormat> 標籤下指定佈局來決定如何將 Log4j2 日誌配置為純文本或 JSON 輸出。

在此範例中,每一行前面都會以文字模式加上日期、時間、請求 ID、日誌層級和類別名稱。在 JSON 模式下<JsonTemplateLayout>,會與 aws-lambda-java-log4j2 程式庫一起隨附的組態搭配使用。

SLF4J 是使用 Java 程式碼進行日誌記錄的外觀程式庫。在您的函數程式碼中,您可以使用 SLF4J 記錄器工廠來擷取帶有日誌層級方法的記錄器,如 info()warn()。在您的建置組態中,您可將日誌記錄程式庫和 SLF4J 轉接器包含在 classpath 中。透過在建置配置中更改程式庫,您可以在不更改函數代碼的情況下更改記錄器類型。需要 SLF4J 才能從 SDK for Java 中擷取日誌。

在下面範例程式碼中,處理常式類別會使用 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 調用事件 (預設為停用)

  • 透過日誌採樣僅列印調用百分比的所有日誌 (預設為停用)

  • 在任何時間點將其他金鑰附加至結構化日誌

  • 使用自訂日誌格式化程式 (自帶格式化程式),以與組織的日誌記錄 RFC 相容的結構輸出日誌。

使用 Powertools for AWS Lambda (Java) 和 AWS SAM 進行結構化日誌記錄

請依照以下步驟操作,使用 AWS SAM 透過整合式 Powertools for AWS Lambda (Java) 模組,下載、建置和部署範例 Hello World Java 應用程式。此應用程式實作了基本 API 後端,並使用 Powertools 發送日誌、指標和追蹤。其包含 Amazon API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時,Lambda 函數會調用、使用內嵌指標格式將日誌和指標傳送至 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 may not have authorization defined, Is this okay?,確保輸入 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 日誌。如需詳細資訊,請參閱《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 主控台來檢視日誌輸出。

如果可以從內嵌程式碼編輯器測試您的程式碼,您會在執行結果中找到日誌。使用主控台測試功能以調用函數時,您會在詳細資訊區段找到日誌輸出

在 CloudWatch 主控台中檢視 記錄

您可以使用 Amazon CloudWatch 主控台來檢視所有 Lambda 函數調用的日誌。

若要在 CloudWatch 主控台上檢視日誌
  1. 在 CloudWatch 主控台上開啟 日誌群組 頁面。

  2. 選擇您的函數的日誌群組 (/aws/lambda/your-function-name)。

  3. 選擇日誌串流

每個日誌串流都會對應至函式的執行個體。當您更新 Lambda 函數,以及建立額外執行個體以處理多個並行調用時,便會出現日誌串流。若要尋找特定調用的日誌,建議使用 AWS X-Ray 來檢測函數。X-Ray 會在追蹤內記錄有關請求和日誌串流的詳細資訊。

使用 AWS Command Line Interface (AWS CLI) 檢視日誌

AWS CLI 是開放原始碼工具,可讓您在命令列 shell 中使用命令來與 AWS 服務互動。若要完成本節中的步驟,您必須擁有 AWS CLI 版本 2

您可以透過 AWS CLI,使用 --log-type 命令選項來擷取要調用的日誌。其回應將包含 LogResult 欄位,內含該次調用的 base64 編碼日誌 (最大達 4 KB)。

範例 擷取日誌 ID

下列範例顯示如何從名稱為 my-function 的函數的 LogResult 欄位來擷取日誌 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。若要取得更多資訊,請參閱《AWS Command Line Interface 使用者指南第 2 版》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 和 Ubuntu on Windows 上使用。macOS 使用者可能需要使用 base64 -D

範例 get-logs.sh 指令碼

在相同的命令提示中,使用下列指令碼下載最後五個日誌事件。該指令碼使用 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。若要取得更多資訊,請參閱《AWS Command Line Interface 使用者指南第 2 版》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
範例 擷取最後五個記錄事件

在相同的命令提示中,執行下列指令碼以取得最後五個日誌事件。

./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 - Java 函數集合,其中包含如何處理來自各種服務 (例如 Amazon API Gateway、Amazon SQS 和 Amazon Kinesis) 事件的骨架程式碼。這些函數使用最新版 aws-lambda-java-events 程式庫 (3.0.0 及更新版)。這些範例不需要 AWS 開發套件做為相依項目。

  • s3-java - 一種 Java 函數,它處理來自 Amazon S3 的通知事件,並使用 Java Class Library (JCL) 以從上傳的映像檔案建立縮圖。

  • custom-serialization – 如何使用常用程式庫 (例如 fastJson、Gson、Moshi 和 jackson-jr) 實作自訂序列化的範例。

  • 使用 API Gateway 調用 Lambda 函數 - 一個 Java 函數,其可掃描包含員工資訊的 Amazon DynamoDB 資料表。然後,其會使用 Amazon Simple Notification Service 向員工傳送文字訊息,慶祝他們的工作週年紀念日。此範例使用 API Gateway 調用函數。

java-basic 範例應用程式會顯示支援日誌記錄測試的最小日誌記錄組態。處理常式程式碼會使用內容物件提供的 LambdaLogger 記錄器。對於測試,應用程式會使用實作具有 Log4j2 記錄器的 LambdaLogger 介面的自訂 TestLogger 類別。它會使用 SLF4J 作為與 AWS 開發套件兼容的外觀。建置輸出中會排除記錄程式庫,使部署套件不會變太大。