Node.js Lambda 함수 로깅 및 모니터링 - AWS Lambda

Node.js Lambda 함수 로깅 및 모니터링

AWS Lambda는 자동으로 Lambda 함수를 모니터링하고 로그를 Amazon CloudWatch로 보냅니다. Lambda 함수는 함수의 각 인스턴스에 대한 CloudWatch Logs 로그 그룹 및 로그 스트림과 함께 제공됩니다. Lambda 런타임 환경은 각 호출에 관한 세부 정보를 로그 스트림에 전송하며, 함수 코드에서 로그 및 그 외 출력을 중계합니다. 자세한 내용은 Lambda와 함께 CloudWatch 로그 사용 단원을 참조하십시오.

이 페이지에서는 AWS Command Line Interface, Lambda 콘솔 또는 CloudWatch 콘솔을 사용하여 Lambda 함수 코드의 로그 출력하고 액세스 로그를 생성하는 방법에 대해 설명합니다.

로그를 반환하는 함수 생성

함수 코드의 로그를 출력하려면, 콘솔 객체에서 메서드를 사용하거나, stdout 또는 stderr에 쓰는 로깅 라이브러리를 사용합니다. 다음 예제는 환경 변수의 값과 이벤트 객체를 로깅합니다.

참고

입력을 로깅할 때 입력 검증 및 출력 인코딩과 같은 기술을 사용하는 것이 좋습니다. 입력 데이터를 직접 로깅하는 경우 공격자가 해당 코드를 사용해서 변조를 감지하기 어렵게 만들고, 로그 항목을 위조하거나, 로그 모니터를 우회할 수 있습니다. 자세한 내용은 Common Weakness EnumerationImproper Output Neutralization for Logs를 참조하세요.

예 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 런타임은 각 호출에 대해 START, ENDREPORT 라인을 로그합니다. 함수에 의해 로그된 각 항목에는 타임스탬프, 요청 ID, 로그 수준을 추가합니다. 보고서 행은 다음과 같은 세부 정보를 제공합니다.

REPORT 행 데이터 필드
  • RequestId – 호출의 고유한 요청 ID입니다.

  • 지속시간 – 함수의 핸들러 메서드가 이벤트를 처리하는 데 걸린 시간입니다.

  • 청구 기간 – 호출에 대해 청구된 시간입니다.

  • 메모리 크기 - 함수에 할당된 메모리 양입니다.

  • 사용된 최대 메모리 – 함수에서 사용한 메모리 양입니다. 간접 호출이 실행 환경을 공유하는 경우 Lambda는 모든 간접 호출에서 사용된 최대 메모리를 보고합니다. 이 동작으로 인해 보고된 값이 예상보다 높을 수 있습니다.

  • 초기화 기간 – 제공된 첫 번째 요청의 경우 런타임이 핸들러 메서드 외부에서 함수를 로드하고 코드를 실행하는 데 걸린 시간입니다.

  • XRAY TraceId – 추적된 요청의 경우 AWS X-Ray 추적 ID입니다.

  • SegmentId - 추적된 요청의 경우 X-Ray 세그먼트 ID입니다.

  • 샘플링 완료(Sampled) – 추적된 요청의 경우 샘플링 결과입니다.

Lambda 콘솔, CloudWatch Logs 콘솔 또는 명령줄에서 로그를 볼 수 있습니다.

Node.js에서 Lambda 고급 로깅 제어 사용

함수의 로그를 캡처, 처리 및 사용하는 방법을 더 잘 제어할 수 있도록 지원되는 Node.js 런타임에 대한 다음의 로깅 옵션을 구성할 수 있습니다.

  • 로그 형식 - 함수 로그의 경우 일반 텍스트와 구조화된 JSON 형식 중에서 선택

  • 로그 수준 - JSON 형식의 로그의 경우, Lambda가 Amazon CloudWatch로 전송하는 로그의 세부 수준(ERROR, DEBUG 또는 INFO 등)을 선택

  • 로그 그룹 - 함수가 로그를 보내는 CloudWatch 로그 그룹을 선택

이러한 로깅 옵션에 대한 자세한 내용과 이를 사용하도록 함수를 구성하는 방법에 대한 지침은 Lambda 함수에 대한 고급 로깅 제어 구성을 참조하세요.

Node.js Lambda 함수에서 로그 형식 및 로그 수준 옵션을 사용하려면 다음 섹션의 지침을 참조하세요.

Node.js에서 구조화된 JSON 로그 사용

함수의 로그 형식으로 JSON을 선택하면 Lambda는 console.trace, console.debug, console.log, console.info, console.errorconsole.warn의 콘솔 메서드를 사용gksms 로그 출력을 구조화된 JSON으로 CloudWatch에 전송합니다. 각 JSON 로그 객체에는 다음 키가 있는 4개의 키 값 페어가 포함되어 있습니다.

  • "timestamp" - 로그 메시지가 생성된 시간

  • "level" - 메시지에 할당된 로그 수준

  • "message" - 로그 메시지의 내용

  • "requestId" - 함수 간접 호출의 고유한 요청 ID

함수에서 사용하는 로깅 방법에 따라 이 JSON 객체에 추가 키 페어가 포함될 수도 있습니다. 예를 들어 함수가 console 메서드를 통해 여러 인수를 사용하여 오류 객체를 기록하는 경우 JSON 객체에는 키 errorMessage, errorType, stackTrace와 함께 추가 키 값 페어가 포함됩니다.

코드에서 이미 AWS Lambda용 Powertools 같은 다른 로깅 라이브러리를 사용하여 JSON 구조화된 로그를 생성하는 경우에는 변경할 필요가 없습니다. Lambda는 이미 JSON으로 인코딩된 로그를 이중 인코딩하지 않으므로 함수의 애플리케이션 로그는 이전과 같이 계속 캡처됩니다.

AWS Lambda용 Powertools 로깅 패키지를 사용하여 Node.js 런타임에서 JSON 구조의 로그를 생성하는 방법에 대한 자세한 내용은 TypeScript Lambda 함수 로깅 및 모니터링을 참조하세요.

JSON 형식의 로그 출력 예제

다음 예제는 함수의 로그 형식을 JSON으로 설정할 때 단일 및 다중 인수를 포함한 console 메서드를 사용하여 생성된 다양한 로그 출력이 CloudWatch Logs에 캡처되는 방법을 보여줍니다.

첫 번째 예제에서는 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 Logs로 전송하는 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 Logs에 출력하는 방법을 보여줍니다. 여러 인수를 사용하여 오류 객체를 기록하는 경우 Lambda는 errorMessage, errorType, stackTrace 필드를 로그 출력에 추가합니다.

예 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 메서드에 제공된 첫 번째 오류 유형에서 추가 필드 errorMessage, errorType, stackTrace가 추출됩니다.

구조화된 JSON 로그가 포함된 임베디드 메트릭 형식(EMF) 클라이언트 라이브러리 사용

AWS는 임베디드 지표 형식 로그(EMF)를 생성하는 데 사용할 수 있는 오픈 소스 클라이언트 라이브러리를 제공합니다. 이러한 라이브러리를 사용하는 기존 함수를 소유하고 있고 함수의 로그 형식을 JSON으로 변경하면 CloudWatch가 코드에서 내보내는 지표를 더 이상 인식하지 못할 수 있습니다.

현재 코드에서 console.log를 사용하거나 또는 AWS Lambda용 Powertools(TypeScript)를 사용하여 직접 EMF 로그를 내보내는 경우에도 함수의 로그 형식을 JSON으로 변경하면 CloudWatch에서 해당 로그를 구문분석할 수 없습니다.

중요

CloudWatch에서 함수의 EMF 로그를 계속해서 적절하게 구문분석하려면 EMFAWS Lambda용 Powertools 라이브러리를 최신 버전으로 업데이트합니다. 또한 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 구조화된 로그를 코드에 만들 수 있습니다. 예를 들어 AWS Lambda용 Powertools를 사용하여 코드로부터 JSON 구조화된 로그 출력을 생성할 수 있습니다. Powertools를 Node.js 런타임과 함께 사용하는 방법에 대한 자세한 내용은 TypeScript Lambda 함수 로깅 및 모니터링을 참조하세요.

    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는 요청 및 로그 스트림에 대한 세부 정보를 기록합니다.

AWS Command Line Interface(AWS CLI)(을)를 사용하여 로그 보기

AWS CLI은(는) 명령줄 셸의 명령을 사용하여 AWS 서비스와 상호 작용할 수 있는 오픈 소스 도구입니다. 이 섹션의 단계를 완료하려면 다음이 필요합니다.

AWS CLI를 사용하면 --log-type 명령 옵션을 통해 호출에 대한 로그를 검색할 수 있습니다. 호출에서 base64로 인코딩된 로그를 최대 4KB까지 포함하는 LogResult 필드가 응답에 포함됩니다.

예 로그 ID 검색

다음 예제에서는 LogResult이라는 함수의 my-function 필드에서 로그 ID를 검색하는 방법을 보여줍니다.

aws lambda invoke --function-name my-function out --log-type Tail

다음 결과가 표시됩니다:

{ "StatusCode": 200, "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...", "ExecutedVersion": "$LATEST" }
예 decode the logs

동일한 명령 프롬프트에서 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

cli-binary-format 옵션은 AWS CLI 버전 2를 사용할 때 필요합니다. 이 설정을 기본 설정으로 지정하려면 aws configure set cli-binary-format raw-in-base64-out을(를) 실행하세요. 자세한 내용은 AWS CLI 지원되는 글로벌 명령줄 옵션을 AWS Command Line Interface 사용 설명서 버전 2에서 참조하세요.

다음 결과가 표시됩니다.

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 스크립트

동일한 명령 프롬프트에서 다음 스크립트를 사용하여 마지막 5개 로그 이벤트를 다운로드합니다. 이 스크립트는 sed를 사용하여 출력 파일에서 따옴표를 제거하고, 로그를 사용할 수 있는 시간을 허용하기 위해 15초 동안 대기합니다. 출력에는 Lambda의 응답과 get-log-events 명령의 출력이 포함됩니다.

다음 코드 샘플의 내용을 복사하고 Lambda 프로젝트 디렉터리에 get-logs.sh로 저장합니다.

cli-binary-format 옵션은 AWS CLI 버전 2를 사용할 때 필요합니다. 이 설정을 기본 설정으로 지정하려면 aws configure set cli-binary-format raw-in-base64-out을(를) 실행하세요. 자세한 내용은 AWS CLI 지원되는 글로벌 명령줄 옵션을 AWS Command Line Interface 사용 설명서 버전 2에서 참조하세요.

#!/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" }

로그 삭제

함수를 삭제해도 로그 그룹이 자동으로 삭제되지 않습니다. 로그를 무기한 저장하지 않으려면 로그 그룹을 삭제하거나 로그가 자동으로 삭제되는 보존 기간을 구성하세요.