Node.js 中的 AWS Lambda 函數記錄 - AWS Lambda

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

Node.js 中的 AWS Lambda 函數記錄

AWS Lambda代表您自動監控 Lambda 函數,並將日誌傳送到 Amazon CloudWatch。您的 Lambda 函數隨附一個 CloudWatch 日誌記錄群組和函數每個執行個體的日誌串流。Lambda 執行期環境會將每次調用的詳細資訊傳送至日誌串流,並且轉傳來自函數程式碼的日誌及其他輸出。如需詳細資訊,請參閱 使用 Amazon CloudWatch 日誌 AWS Lambda

本頁說明如何從 Lambda 函數的程式碼產生記錄輸出,或使用 Lambda 主控台或主控台存取 CloudWatch 日誌。AWS Command Line Interface

建立傳回日誌的函數

若要由您的函式程式碼輸出日誌,您可以在主控台物件上使用方法,或任何能寫入 stdoutstderr 的記錄程式庫。下列範例會記錄環境變數和事件物件的值。

範例 index.js 檔案 - 記錄
exports.handler = async function(event, context) { console.log("ENVIRONMENT VARIABLES\n" + JSON.stringify(process.env, null, 2)) console.info("EVENT\n" + JSON.stringify(event, null, 2)) console.warn("Event not processed.") return context.logStreamName }
範例 記錄格式
START RequestId: c793869b-ee49-115b-a5b6-4fd21e8dedac Version: $LATEST 2019-06-07T19:11:20.562Z c793869b-ee49-115b-a5b6-4fd21e8dedac INFO ENVIRONMENT VARIABLES { "AWS_LAMBDA_FUNCTION_VERSION": "$LATEST", "AWS_LAMBDA_LOG_GROUP_NAME": "/aws/lambda/my-function", "AWS_LAMBDA_LOG_STREAM_NAME": "2019/06/07/[$LATEST]e6f4a0c4241adcd70c262d34c0bbc85c", "AWS_EXECUTION_ENV": "AWS_Lambda_nodejs12.x", "AWS_LAMBDA_FUNCTION_NAME": "my-function", "PATH": "/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin", "NODE_PATH": "/opt/nodejs/node10/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules", ... } 2019-06-07T19:11:20.563Z c793869b-ee49-115b-a5b6-4fd21e8dedac INFO EVENT { "key": "value" } 2019-06-07T19:11:20.564Z c793869b-ee49-115b-a5b6-4fd21e8dedac WARN Event not processed. END RequestId: c793869b-ee49-115b-a5b6-4fd21e8dedac REPORT RequestId: c793869b-ee49-115b-a5b6-4fd21e8dedac Duration: 128.83 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 74 MB Init Duration: 166.62 ms XRAY TraceId: 1-5d9d007f-0a8c7fd02xmpl480aed55ef0 SegmentId: 3d752xmpl1bbe37e Sampled: true

Node.js 執行時間會記錄每次呼叫的 STARTENDREPORT 行。它會將時間戳記、請求 ID 和日誌層級新增到函式所記錄的每個項目。報告明細行提供下列詳細資訊。

REPORT 行資料欄位
  • RequestId— 呼叫的唯一要求 ID。

  • 持續時間 - 函數的處理常式方法處理事件所花費的時間量。

  • 計費持續時間 - 調用的計費時間量。

  • 記憶體大小 - 分配給函數的記憶體數量。

  • 使用的記憶體上限 - 函數所使用的記憶體數量。

  • 初始化持續時間 - 對於第一個提供的請求,這是執行期載入函數並在處理常式方法之外執行程式碼所花費的時間量。

  • XRAY TraceId — 針對追蹤的要求,則為AWS X-Ray追蹤識別碼。

  • SegmentId— 針對追蹤的請求,X-Ray 區段 ID。

  • 已取樣 - 對於追蹤的請求,這是取樣結果。

您可以在 Lambda 主控台、 CloudWatch 記錄主控台或從命令列檢視記錄。

搭配 Node.js 使用 Lambda 進階日誌控制項

為了讓您更妥善地控制擷取、處理和使用函數日誌的方式,您可以針對支援的 Node.js 執行期設定下列記錄選項:

  • 日誌格式 - 在純文字和結構化 JSON 格式之間為您的日誌進行選擇

  • 誌級別-對於 JSON 格式的日誌,選擇 Lambda 發送到 Amazon 的日誌詳細級別 CloudWatch,例如錯誤,調試或信息

  • 誌組-選擇您的功能發送日誌的日誌組 CloudWatch

如需這些日誌選項的詳細資訊,以及如何設定函數以使用這些選項的說明,請參閱 設定 Lambda 函數的進階日誌控制項

若要使用日誌格式和日誌層級選項與 Node.js Lambda 函數搭配使用,請參閱以下各章節中的指引。

搭配 Node.js 使用結構化的 JSON 日誌

如果您為函數的記錄格式選取 JSON,Lambda 會使用、、console.traceconsole.debugconsole.logconsole.info和的主控台方法將記錄輸出傳送console.warn至 CloudWatch 結構化 JSON。console.error每個 JSON 日誌物件都包含至少四個鍵值對,其中包含下列索引鍵:

  • "timestamp" - 產生日誌訊息的時間

  • "level" - 指派給訊息的日誌層級

  • "message" - 日誌訊息的內容

  • "requestId" - 進行調用的唯一請求 ID。

依據您的函數使用的記錄方法,此 JSON 物件還可能包含其他鍵值對。例如,如果您的函數使用 console 方法來記錄使用多個引數的錯誤物件,JSON 物件將包含具有索引鍵 errorMessageerrorTypestackTrace 的額外鍵值對。

如果您的程式碼已經使用另一個記錄程式庫 (例如 Powertools for AWS Lambda) 來生成 JSON 結構化日誌,則不需要進行任何更改。Lambda 不會對任何已經進行 JSON 編碼的日誌進行雙重編碼,因此您函數的應用程式日誌將繼續像以前一樣被擷取。

如需有關使用 Powertools for AWS Lambda 日誌封裝以在 Node .js 執行期中建立 JSON 結構化日誌的詳細資訊,請參閱AWS Lambda功能登錄 TypeScript

JSON 格式日誌輸出範例

下列範例顯示當您將函數的記錄格式設定為 JSON 時,如何在 CloudWatch 記錄檔中擷取使用具有單引數和多個引數的console方法產生的各種記錄輸出。

第一個範例使用 console.error 方法輸出簡單字串。

範例 Node.js 日誌程式碼
export const handler = async (event) => { console.error("This is a warning message"); ... }
範例 JSON 日誌記錄
{ "timestamp":"2023-11-01T00:21:51.358Z", "level":"ERROR", "message":"This is a warning message", "requestId":"93f25699-2cbf-4976-8f94-336a0aa98c6f" }

您還可以透過 console 方法使用單個或多個引數輸出結構更複雜的日誌訊息。在下一個範例中,您將使用 console.log 與單個引數輸出兩個鍵值對。請注意,Lambda 傳送至 CloudWatch 記錄的 JSON 物件中的"message"欄位並未設定字串化。

範例 Node.js 日誌程式碼
export const handler = async (event) => { console.log({data: 12.3, flag: false}); ... }
範例 JSON 日誌記錄
{ "timestamp": "2023-12-08T23:21:04.664Z", "level": "INFO", "requestId": "405a4537-9226-4216-ac59-64381ec8654a", "message": { "data": 12.3, "flag": false } }

在下一個範例中,您要再次使用 console.log 方法建立日誌輸出。這一次,該方法使用兩個引數、一個包含兩個鍵值對的映射和一個識別字串。請注意,在這種情況下,由於您提供了兩個引數,Lambda 會對 "message" 欄位進行字串化。

範例 Node.js 日誌程式碼
export const handler = async (event) => { console.log('Some object - ', {data: 12.3, flag: false}); ... }
範例 JSON 日誌記錄
{ "timestamp": "2023-12-08T23:21:04.664Z", "level": "INFO", "requestId": "405a4537-9226-4216-ac59-64381ec8654a", "message": "Some object - { data: 12.3, flag: false }" }

Lambda 會指派使用 console.log 日誌層級 INFO 產生的輸出。

最後一個範例顯示如何使用這些console方法將錯誤物件輸出至 CloudWatch 記錄檔。請注意,當您使用多個引數記錄錯誤物件時,Lambda 會新增 errorMessageerrorTypestackTrace 欄位至日誌輸出。若要進一步了解 Node.js 中的函數錯誤,請參閱 Node.js 中的 AWS Lambda 函數錯誤

範例 Node.js 日誌程式碼
export const handler = async (event) => { let e1 = new ReferenceError("some reference error"); let e2 = new SyntaxError("some syntax error"); console.log(e1); console.log("errors logged - ", e1, e2); };
範例 JSON 日誌記錄
{ "timestamp": "2023-12-08T23:21:04.632Z", "level": "INFO", "requestId": "405a4537-9226-4216-ac59-64381ec8654a", "message": { "errorType": "ReferenceError", "errorMessage": "some reference error", "stackTrace": [ "ReferenceError: some reference error", " at Runtime.handler (file:///var/task/index.mjs:3:12)", " at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29)" ] } } { "timestamp": "2023-12-08T23:21:04.646Z", "level": "INFO", "requestId": "405a4537-9226-4216-ac59-64381ec8654a", "message": "errors logged - ReferenceError: some reference error\n at Runtime.handler (file:///var/task/index.mjs:3:12)\n at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29) SyntaxError: some syntax error\n at Runtime.handler (file:///var/task/index.mjs:4:12)\n at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29)", "errorType": "ReferenceError", "errorMessage": "some reference error", "stackTrace": [ "ReferenceError: some reference error", " at Runtime.handler (file:///var/task/index.mjs:3:12)", " at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29)" ] }

記錄多個錯誤類型時,會從提供給 console 方法的第一個錯誤類型中擷取額外欄位 errorMessageerrorTypestackTrace

搭配結構化 JSON 日誌使用內嵌指標格式 (EMF) 用戶端程式庫

AWS 提供適用於 Node.js 的開放原始碼的用戶端程式庫,可讓您用來建立內嵌指標格式 (EMF) 日誌。如果您有使用這些庫的現有函數,並且將函數的日誌格式更改為 JSON,則 CloudWatch 可能不再識別代碼發出的指標。

如果您的代碼當前直接使用console.log或使用 Powertools to AWS Lambda (TypeScript) 發出 EMF 日誌,如果 CloudWatch 將函數的日誌格式更改為 JSON,也將無法解析這些日誌。

重要

為了確保您的功能的 EMF 日誌繼續被正確解析 CloudWatch,請將您的 EMFPowertools 的AWS Lambda庫更新為最新版本。如果切換到 JSON 日誌格式,我們也建議您進行測試,以確保與函數的內嵌指標相容。如果您的程式碼直接使用 console.log 發出 EMF 記錄,請變更您的程式碼以將這些指標直接輸出至 stdout,如下列程式碼範例所示。

範例 發出內嵌指標至 stdout 的程式碼
process.stdout.write(JSON.stringify( { "_aws": { "Timestamp": Date.now(), "CloudWatchMetrics": [{ "Namespace": "lambda-function-metrics", "Dimensions": [["functionVersion"]], "Metrics": [{ "Name": "time", "Unit": "Milliseconds", "StorageResolution": 60 }] }] }, "functionVersion": "$LATEST", "time": 100, "requestId": context.awsRequestId } ) + "\n")

搭配 Node.js 使用日誌層級篩選

為了讓 AWS Lambda 根據日誌層級篩選應用程式日誌,您的函數必須使用 JSON 格式的日誌。您可以透過兩種方式達成此操作:

  • 使用標準主控台方法建立日誌輸出,並將函數設定為使用 JSON 日誌格式。然後 AWS Lambda 使用 搭配 Node.js 使用結構化的 JSON 日誌 中所描述的 JSON 物件中的「層級」索引鍵值組篩選日誌輸出。若要瞭解如何設定函數的日誌格式,請參閱 設定 Lambda 函數的進階日誌控制項

  • 使用其他日誌程式庫或方法,在您的程式碼中建立 JSON 結構化日誌,其中包含定義日誌輸出層級的「層級」索引鍵值組。例如,您可以使用 Powertools for AWS Lambda 從您的程式碼生成 JSON 結構化日誌輸出。請參閱 AWS Lambda功能登錄 TypeScript 以瞭解有關在 Node.js 執行期使用 Powertools 的更多資訊。

    若要讓 Lambda 篩選函數的日誌,您還必須在 JSON 日誌輸出中包含 "timestamp" 索引鍵值組。必須以有效的 RFC 3339 時間戳記格式指定時間。如果您沒有提供有效的時間戳記,Lambda 會為日誌指派層級 INFO,並為您新增時間戳記。

當您將函數設定為使用記錄層級篩選時,您可以從下列選項中選取要傳送AWS Lambda至 CloudWatch 記錄檔的記錄層級:

日誌層級 標準用量
TRACE (大多數詳細資訊) 用於追蹤程式碼執行路徑的最精細資訊
DEBUG 系統偵錯的詳細資訊
INFO 記錄函數正常操作的訊息
WARN 有關可能導致未解決意外行為的潛在錯誤的消息
ERROR 有關阻止程式碼按預期執行的問題的訊息
FATAL (最少詳細資訊) 有關導致應用程式停止運作的嚴重錯誤訊息

Lambda 會將所選層級且較低層級的記錄傳送至 CloudWatch。例如,如果您設定 WARN 的日誌層級,Lambda 會傳送相對應於 WARN、ERROR 和 FATAL 層級的日誌檔。

使用 Lambda 主控台

您可以在調用 Lambda 函數之後,使用 Lambda 主控台來檢視日誌輸出。

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

使用控 CloudWatch 制台

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

在 CloudWatch 主控台上檢視記錄檔
  1. 在主控台上開啟 [記錄群組] 頁 CloudWatch 面

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

  3. 選擇日誌串流

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

若要使用會讓日誌和追蹤與 X-Ray 相互關聯的範例應用程式,請參閱 適用於 AWS Lambda 的錯誤處理器範例應用程式

使用 AWS Command Line Interface​ (AWS CLI​)

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

您可以透過 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" }

刪除日誌

當您刪除函數時,不會自動刪除日誌群組。若要避免無限期地儲存日誌,請刪除日誌群組,或設定保留期間,系統會在該時間之後自動刪除日誌。