Rust Lambda 함수 로그 및 모니터링

Rust Lambda 함수 로그 및 모니터링

AWS Lambda가 여러분 대신 Lambda 함수를 자동으로 모니터링하고 로그를 Amazon CloudWatch로 보내요. Lambda 함수에는 CloudWatch Logs 로그 그룹과 함수 인스턴스마다 하나씩의 로그 스트림이 함께 생성돼요. Lambda 런타임 환경은 각 호출에 대한 세부 정보를 로그 스트림으로 보내고, 함수 코드에서 나온 로그와 기타 출력을 전달해요.

자세한 내용은 Lambda 함수 로그를 CloudWatch Logs로 보내기를 참고하세요. 로그 형식 구성에 대한 내용은 JSON 및 일반 텍스트 로그 형식 구성을 참고하세요. 이 페이지에서는 Lambda 함수 코드에서 로그 출력을 만드는 방법을 설명해요.

출처: AWS Lambda 개발자 안내서

본문

로그를 작성하는 함수 만들기

함수 코드에서 로그를 출력하려면 stdout 또는 stderr에 쓰는 아무 로깅 함수(예: println! 매크로)를 사용할 수 있어요. 다음 예시는 함수 핸들러가 시작할 때와 끝나기 직전에 메시지를 출력하기 위해 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
}

Tracing 크레이트로 고급 로깅 구현

Tracing은 구조화된 이벤트 기반 진단 정보를 수집하기 위해 Rust 프로그램을 계측(instrument)하는 프레임워크예요. 이 프레임워크는 구조화된 JSON 로그 메시지 만들기 등 로깅 출력 수준과 형식을 사용자 지정하는 유틸리티를 제공해요. 이 프레임워크를 사용하려면 함수 핸들러를 구현하기 전에 subscriber를 초기화해야 해요. 그런 다음 debug, info, error 같은 tracing 매크로를 사용해서 각 시나리오에 원하는 로깅 수준을 지정할 수 있어요.

예시 — Tracing 크레이트 사용
다음에 유의하세요.

  • 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))]: 이 어노테이션은 핸들러가 호출될 때마다 스팬(span)을 생성해요. 이 스팬은 각 로그 줄에 요청 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 함수를 호출하면 다음과 유사한 두 줄의 로그를 출력해요.

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

더 알아보기 (Learn more)

Lambda 함수 로그를 CloudWatch Logs로 보내는 방법은 Lambda 함수 로그를 CloudWatch Logs로 보내기를 참고하세요.