Rust Lambda 関数のログ記録とモニタリング
注記
「Rust ランタイムクライアント
AWS Lambda は、ユーザーに代わって Lambda 関数を自動的にモニタリングし、Amazon CloudWatch にログを送信します。Lambda 関数には、関数のインスタンスごとに CloudWatch Logs ロググループとログストリームが用意されています。Lambda ランタイム環境は、各呼び出しの詳細をログストリームに送信し、関数のコードからのログやその他の出力を中継します。詳細については、「AWS Lambda での Amazon CloudWatch Logs の使用」を参照してください。このページでは、Lambda 関数のコードからログ出力を生成する方法について説明します。
ログを書く関数の作成
関数コードからログを出力するには、println!
マクロなどの stdout
または stderr
に書き込む任意のログ記録ライブラリを使用できます。次の例は、println!
を使用して、関数ハンドラーの開始時と終了前にメッセージを印刷します。
use lambda_runtime::{service_fn, LambdaEvent, Error}; use serde_json::{json, Value}; async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> { println!("Rust function invoked"); let payload = event.payload; let first_name = payload["firstName"].as_str().unwrap_or("world"); println!("Rust function responds to {}", &first_name); Ok(json!({ "message": format!("Hello, {first_name}!") })) } #[tokio::main] async fn main() -> Result<(), Error> { lambda_runtime::run(service_fn(handler)).await }
トレーシングクレートによる高度なログ記録機能の実装
トレーシングsubscriber
を初期化する必要があります。次に、debug
、info
、error
などのトレースマクロを使用して、各シナリオに必要なログのレベルを指定できます。
例 — トレーシングクレートの使用
次の点に注意してください。
-
tracing_subscriber::fmt().json()
: このオプションが含まれる場合、ログは JSON でフォーマットされます。このオプションを使用するには、tracing-subscriber
のjson
機能を依存関係に含める必要があります (例:tracing-subscriber = { version = "0.3.11", features = ["json"] }
)。 -
#[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))]
: このアノテーションは、ハンドラが呼び出されるたびにスパンを生成します。このスパンは、各ログ行にリクエスト ID を追加します。 -
{ %first_name }
: このコンストラクトは、使用されているログ行にfirst_name
フィールドを追加します。このフィールドの値は、同じ名前の変数に対応します。
use lambda_runtime::{service_fn, Error, LambdaEvent}; use serde_json::{json, Value}; #[tracing::instrument(skip(event), fields(req_id = %event.context.request_id))] async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> { tracing::info!("Rust function invoked"); let payload = event.payload; let first_name = payload["firstName"].as_str().unwrap_or("world"); tracing::info!({ %first_name }, "Rust function responds to event"); Ok(json!({ "message": format!("Hello, {first_name}!") })) } #[tokio::main] async fn main() -> Result<(), Error> { tracing_subscriber::fmt().json() .with_max_level(tracing::Level::INFO) // this needs to be set to remove duplicated information in the log. .with_current_span(false) // this needs to be set to false, otherwise ANSI color codes will // show up in a confusing manner in CloudWatch logs. .with_ansi(false) // disabling time is handy because CloudWatch will add the ingestion time. .without_time() // remove the name of the function from every log entry .with_target(false) .init(); lambda_runtime::run(service_fn(handler)).await }
この Rust 関数が呼び出されると、次のようなログ行が 2 行出力されます。
{"level":"INFO","fields":{"message":"Rust function invoked"},"spans":[{"req_id":"45daaaa7-1a72-470c-9a62-e79860044bb5","name":"handler"}]} {"level":"INFO","fields":{"message":"Rust function responds to event","first_name":"David"},"spans":[{"req_id":"45daaaa7-1a72-470c-9a62-e79860044bb5","name":"handler"}]}