AWS Lambda에서 Python 코드 계측(Instrumenting)
AWS Lambda에서 Python 코드 계측(Instrumenting)
Lambda는 AWS X-Ray와 통합되어 Lambda 애플리케이션을 추적(trace), 디버그, 최적화할 수 있게 도와줘요. X-Ray를 사용하면 애플리케이션의 리소스(Lambda 함수와 다른 AWS 서비스 포함)를 가로지르는 요청을 추적할 수 있죠.
X-Ray로 추적 데이터를 보내려면 다음 세 가지 SDK 라이브러리 중 하나를 사용하면 돼요:
- AWS Distro for OpenTelemetry (ADOT) – OpenTelemetry(OTel) SDK의 안전하고 프로덕션에 적합하며 AWS에서 지원하는 배포판이에요.
- AWS X-Ray SDK for Python – 추적 데이터를 생성해 X-Ray로 보내는 SDK예요.
- Powertools for AWS Lambda (Python) – Serverless 모범 사례를 구현하고 개발 속도를 높이는 개발자 도구 키트예요.
세 SDK 모두 텔레메트리 데이터를 X-Ray 서비스로 보내는 방법을 제공해요. 그러면 X-Ray로 애플리케이션의 성능 지표를 보고, 필터링하고, 인사이트를 얻어 문제와 최적화 기회를 찾을 수 있습니다.
중요
X-Ray와 Powertools for AWS Lambda SDK는 AWS가 제공하는 긴밀하게 통합된 계측 솔루션의 일부예요. ADOT Lambda 레이어(layer)는 업계 표준 추적 계측 방식으로, 일반적으로 더 많은 데이터를 수집하지만 모든 사용 사례에 적합하진 않을 수 있어요. 두 솔루션 중 하나로 X-Ray에서 종단 간 추적(end-to-end tracing)을 구현할 수 있어요. 어떤 걸 고를지 알아보려면 AWS Distro for OpenTelemetry와 X-Ray SDK 중 선택을 참고하세요.
Topics(주제)
- 추적을 위해 Powertools for AWS Lambda (Python)와 AWS SAM 사용
- 추적을 위해 Powertools for AWS Lambda (Python)와 AWS CDK 사용
- ADOT로 Python 함수 계측
- X-Ray SDK로 Python 함수 계측
- Lambda 콘솔로 추적 활성화
- Lambda API로 추적 활성화
- CloudFormation으로 추적 활성화
- X-Ray 추적 해석
- 레이어(layer)에 런타임 의존성 저장 (X-Ray SDK)
본문
추적을 위해 Powertools for AWS Lambda (Python)와 AWS SAM 사용
AWS SAM을 사용해 Powertools for AWS Lambda (Python) 모듈이 통합된 Hello World Python 샘플 애플리케이션을 다운로드하고 빌드하고 배포하려면 아래 단계를 따르세요. 이 애플리케이션은 기본 API 백엔드를 구현하고 로그·메트릭·추적을 내보내기 위해 Powertools를 사용해요. Amazon API Gateway 엔드포인트와 Lambda 함수로 구성되죠. API Gateway 엔드포인트에 GET 요청을 보내면 Lambda 함수가 호출되어 Embedded Metric Format으로 로그와 메트릭을 CloudWatch로 보내고, 추적을 AWS X-Ray로 보냅니다. 함수는 hello world 메시지를 반환해요.
사전 요구 사항
이 섹션의 단계를 완료하려면 다음이 필요해요:
- Python 3.11
- AWS CLI version 2
- AWS SAM CLI version 1.75 이상. AWS SAM CLI의 이전 버전을 쓰고 있다면 AWS SAM CLI 업그레이드를 참고하세요.
샘플 AWS SAM 애플리케이션 배포
-
Hello World Python 템플릿으로 애플리케이션을 초기화합니다.
sam init --app-template hello-world-powertools-python --name sam-app --package-type Zip --runtime python3.11 --no-tracing -
앱을 빌드합니다.
cd sam-app && sam build -
앱을 배포합니다.
sam deploy --guided -
화면의 안내를 따릅니다. 대화형 환경에서 제공되는 기본 옵션을 수락하려면
Enter를 누르세요. 참고
HelloWorldFunction may not have authorization defined, Is this okay? 에서는 반드시y를 입력하세요. -
배포된 애플리케이션의 URL을 가져옵니다:
aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text -
API 엔드포인트를 호출합니다:
curl -X GET {{<URL_FROM_PREVIOUS_STEP>}}성공하면 다음 응답이 보일 거예요:
{"message":"hello world"} -
함수의 추적을 가져오려면 sam traces를 실행합니다.
sam traces추적 출력은 다음과 같아요:
New XRay Service Graph Start time: 2023-02-03 14:59:50+00:00 End time: 2023-02-03 14:59:50+00:00 Reference Id: 0 - (Root) AWS::Lambda - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [1] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.924 Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.016 Reference Id: 2 - client - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [0] Summary_statistics: - total requests: 0 - ok count(2XX): 0 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0 XRay Event [revision 1] at (2023-02-03T14:59:50.204000) with id (1-63dd2166-434a12c22e1307ff2114f299) and duration (0.924s) - 0.924s - sam-app-HelloWorldFunction-YBg8yfYtOc9j [HTTP: 200] - 0.016s - sam-app-HelloWorldFunction-YBg8yfYtOc9j - 0.739s - Initialization - 0.016s - Invocation - 0.013s - ## lambda_handler - 0.000s - ## app.hello - 0.000s - Overhead -
이것은 인터넷을 통해 접근 가능한 공개 API 엔드포인트예요. 테스트 후에는 엔드포인트를 삭제하는 걸 권장해요.
sam delete
X-Ray는 애플리케이션에 대한 모든 요청을 추적하진 않아요. X-Ray는 추적이 효율적이면서도 모든 요청의 대표적인 샘플을 제공하도록 샘플링 알고리즘을 적용해요. 샘플링 비율은 초당 1개 요청과 추가 요청의 5%예요. 함수의 X-Ray 샘플링 비율은 구성할 수 없습니다.
추적을 위해 Powertools for AWS Lambda (Python)와 AWS CDK 사용
AWS CDK을 사용해 Powertools for AWS Lambda (Python) 모듈이 통합된 Hello World Python 샘플 애플리케이션을 다운로드하고 빌드하고 배포하려면 아래 단계를 따르세요. 이 애플리케이션은 기본 API 백엔드를 구현하고 로그·메트릭·추적을 내보내기 위해 Powertools를 사용해요. Amazon API Gateway 엔드포인트와 Lambda 함수로 구성되죠. API Gateway 엔드포인트에 GET 요청을 보내면 Lambda 함수가 호출되어 Embedded Metric Format으로 로그와 메트릭을 CloudWatch로 보내고, 추적을 AWS X-Ray로 보냅니다. 함수는 hello world 메시지를 반환해요.
사전 요구 사항
이 섹션의 단계를 완료하려면 다음이 필요해요:
- Python 3.11
- AWS CLI version 2
- AWS CDK version 2
- AWS SAM CLI version 1.75 이상. AWS SAM CLI의 이전 버전을 쓰고 있다면 AWS SAM CLI 업그레이드를 참고하세요.
샘플 AWS CDK 애플리케이션 배포
-
새 애플리케이션용 프로젝트 디렉토리를 만듭니다.
mkdir hello-world cd hello-world -
앱을 초기화합니다.
cdk init app --language python -
Python 의존성을 설치합니다.
pip install -r requirements.txt -
루트 폴더 아래에 lambda_function 디렉토리를 만듭니다.
mkdir lambda_function cd lambda_function -
app.py 파일을 만들고 다음 코드를 추가합니다. 이는 Lambda 함수 코드예요.
from aws_lambda_powertools.event_handler import APIGatewayRestResolver from aws_lambda_powertools.utilities.typing import LambdaContext from aws_lambda_powertools.logging import correlation_paths from aws_lambda_powertools import Logger from aws_lambda_powertools import Tracer from aws_lambda_powertools import Metrics from aws_lambda_powertools.metrics import MetricUnit app = APIGatewayRestResolver() tracer = Tracer() logger = Logger() metrics = Metrics(namespace="PowertoolsSample") @app.get("/hello") @tracer.capture_method def hello(): # adding custom metrics # See: https://docs.powertools.aws.dev/lambda-python/latest/core/metrics/ metrics.add_metric(name="HelloWorldInvocations", unit=MetricUnit.Count, value=1) # structured log # See: https://docs.powertools.aws.dev/lambda-python/latest/core/logger/ logger.info("Hello world API - HTTP 200") return {"message": "hello world"} # Enrich logging with contextual information from Lambda @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) # Adding tracer # See: https://docs.powertools.aws.dev/lambda-python/latest/core/tracer/ @tracer.capture_lambda_handler # ensures metrics are flushed upon request completion/failure and capturing ColdStart metric @metrics.log_metrics(capture_cold_start_metric=True) def lambda_handler(event: dict, context: LambdaContext) -> dict: return app.resolve(event, context) -
hello_world 디렉토리를 엽니다. hello_world_stack.py라는 파일이 보일 거예요.
cd .. cd hello_world -
hello_world_stack.py를 열고 다음 코드를 추가합니다. 여기에는 Lambda 함수를 만들고 Powertools용 환경 변수를 구성하며 로그 보존 기간을 1주일로 설정하는 Lambda Constructor와 REST API를 만드는 ApiGatewayv1 Constructor가 포함되어 있어요.
from aws_cdk import ( Stack, aws_apigateway as apigwv1, aws_lambda as lambda_, CfnOutput, Duration ) from constructs import Construct class HelloWorldStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Powertools Lambda Layer powertools_layer = lambda_.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", # At the moment we wrote this example, the aws_lambda_python_alpha CDK constructor is in Alpha, o we use layer to make the example simpler # See https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_lambda_python_alpha/README.html # Check all Powertools layers versions here: https://docs.powertools.aws.dev/lambda-python/latest/#lambda-layer layer_version_arn=f"arn:aws:lambda:{self.region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:21" ) function = lambda_.Function(self, 'sample-app-lambda', runtime=lambda_.Runtime.PYTHON_3_11, layers=[powertools_layer], code = lambda_.Code.from_asset("./lambda_function/"), handler="app.lambda_handler", memory_size=128, timeout=Duration.seconds(3), architecture=lambda_.Architecture.X86_64, environment={ "POWERTOOLS_SERVICE_NAME": "PowertoolsHelloWorld", "POWERTOOLS_METRICS_NAMESPACE": "PowertoolsSample", "LOG_LEVEL": "INFO" } ) apigw = apigwv1.RestApi(self, "PowertoolsAPI", deploy_options=apigwv1.StageOptions(stage_name="dev")) hello_api = apigw.root.add_resource("hello") hello_api.add_method("GET", apigwv1.LambdaIntegration(function, proxy=True)) CfnOutput(self, "apiUrl", value=f"{apigw.url}hello") -
애플리케이션을 배포합니다.
cd .. cdk deploy -
배포된 애플리케이션의 URL을 가져옵니다:
aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?OutputKey==`apiUrl`].OutputValue' --output text -
API 엔드포인트를 호출합니다:
curl -X GET {{<URL_FROM_PREVIOUS_STEP>}}성공하면 다음 응답이 보일 거예요:
{"message":"hello world"} -
함수의 추적을 가져오려면 sam traces를 실행합니다.
sam traces추적 출력은 다음과 같아요:
New XRay Service Graph Start time: 2023-02-03 14:59:50+00:00 End time: 2023-02-03 14:59:50+00:00 Reference Id: 0 - (Root) AWS::Lambda - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [1] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.924 Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [] Summary_statistics: - total requests: 1 - ok count(2XX): 1 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0.016 Reference Id: 2 - client - sam-app-HelloWorldFunction-YBg8yfYtOc9j - Edges: [0] Summary_statistics: - total requests: 0 - ok count(2XX): 0 - error count(4XX): 0 - fault count(5XX): 0 - total response time: 0 XRay Event [revision 1] at (2023-02-03T14:59:50.204000) with id (1-63dd2166-434a12c22e1307ff2114f299) and duration (0.924s) - 0.924s - sam-app-HelloWorldFunction-YBg8yfYtOc9j [HTTP: 200] - 0.016s - sam-app-HelloWorldFunction-YBg8yfYtOc9j - 0.739s - Initialization - 0.016s - Invocation - 0.013s - ## lambda_handler - 0.000s - ## app.hello - 0.000s - Overhead -
이것은 인터넷을 통해 접근 가능한 공개 API 엔드포인트예요. 테스트 후에는 엔드포인트를 삭제하는 걸 권장해요.
cdk destroy
ADOT로 Python 함수 계측
ADOT는 OTel SDK로 텔레메트리 데이터를 수집하는 데 필요한 모든 것을 패키징한 완전 관리형 Lambda 레이어를 제공해요. 이 레이어를 사용하면 함수 코드를 전혀 수정하지 않고도 Lambda 함수를 계측할 수 있죠. 또한 레이어를 구성해 OTel의 커스텀 초기화를 할 수도 있어요. 자세한 내용은 ADOT 문서의 Lambda에서 ADOT Collector 커스텀 구성을 참고하세요.
Python 런타임에서는 ADOT Python용 AWS 관리형 Lambda 레이어를 추가해 함수를 자동으로 계측할 수 있어요. 이 레이어는 arm64와 x86_64 아키텍처 모두에서 동작해요. 이 레이어를 추가하는 자세한 방법은 ADOT 문서의 Python용 AWS Distro for OpenTelemetry Lambda 지원을 참고하세요.
X-Ray SDK로 Python 함수 계측
Lambda 함수가 애플리케이션의 다른 리소스에 호출하는 상세 정보를 기록하려면 AWS X-Ray SDK for Python을 사용할 수도 있어요. SDK를 얻으려면 aws-xray-sdk 패키지를 애플리케이션의 의존성에 추가하세요.
jsonpickle==1.3
aws-xray-sdk==2.4.3
함수 코드에서는 aws_xray_sdk.core 모듈로 boto3 라이브러리를 패치(patch)해 AWS SDK 클라이언트를 계측할 수 있어요.
예제 function – AWS SDK 클라이언트 추적
import boto3
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
logger = logging.getLogger()
logger.setLevel(logging.INFO)
patch_all()
client = boto3.client('lambda')
client.get_account_settings()
def lambda_handler(event, context):
logger.info('## ENVIRONMENT VARIABLES\r' + jsonpickle.encode(dict(**os.environ)))
...
올바른 의존성을 추가하고 필요한 코드 변경을 마친 뒤, Lambda 콘솔 또는 API를 통해 함수 구성에서 추적을 활성화하세요.
Lambda 콘솔로 추적 활성화
콘솔에서 Lambda 함수의 활성 추적(active tracing)을 켜려면 다음 단계를 따르세요.
활성 추적 켜기
- Lambda 콘솔의 함수 페이지를 엽니다.
- 함수를 선택합니다.
- Configuration(구성)을 선택한 다음 Monitoring and operations tools(모니터링 및 운영 도구)를 선택합니다.
- Additional monitoring tools(추가 모니터링 도구)에서 Edit(편집)을 선택합니다.
- CloudWatch Application Signals and AWS X-Ray 아래에서 Lambda service traces에 대해 Enable(활성화)을 선택합니다.
- Save(저장)를 선택합니다.
Lambda API로 추적 활성화
AWS CLI 또는 AWS SDK로 Lambda 함수에서 추적을 구성하려면 다음 API 작업을 사용하세요:
다음 예제 AWS CLI 명령은 my-function이라는 함수의 활성 추적을 활성화해요.
aws lambda update-function-configuration --function-name my-function \
--tracing-config Mode=Active
추적 모드는 함수 버전을 게시할 때 버전별 구성(version-specific configuration)의 일부가 돼요. 게시된 버전에서는 추적 모드를 변경할 수 없습니다.
CloudFormation으로 추적 활성화
CloudFormation 템플릿에서 AWS::Lambda::Function 리소스의 추적을 활성화하려면 TracingConfig 속성을 사용하세요.
예제 function-inline.yml – 추적 구성
Resources:
function:
Type: [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
Properties:
TracingConfig:
Mode: Active
...
AWS Serverless Application Model(AWS SAM) AWS::Serverless::Function 리소스에는 Tracing 속성을 사용하세요.
예제 template.yml – 추적 구성
Resources:
function:
Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
Properties:
Tracing: Active
...
X-Ray 추적 해석
함수는 추적 데이터를 X-Ray에 업로드할 권한이 필요해요. Lambda 콘솔에서 추적을 활성화하면 Lambda가 함수의 실행 역할에 필요한 권한을 추가해요. 그렇지 않으면 실행 역할에 AWSXRayDaemonWriteAccess 정책을 추가하세요.
활성 추적을 구성한 뒤에는 애플리케이션을 통과하는 특정 요청을 관찰할 수 있어요. X-Ray 서비스 그래프는 애플리케이션과 모든 구성 요소에 대한 정보를 보여줘요. 다음 예제는 함수 두 개가 있는 애플리케이션을 보여줍니다. 기본 함수는 이벤트를 처리하고 가끔 오류를 반환해요. 맨 위의 두 번째 함수는 첫 번째 함수의 로그 그룹에 나타난 오류를 처리하며, AWS SDK를 사용해 X-Ray, Amazon Simple Storage Service(Amazon S3), Amazon CloudWatch Logs를 호출합니다.

X-Ray는 애플리케이션에 대한 모든 요청을 추적하진 않아요. X-Ray는 추적이 효율적이면서도 모든 요청의 대표적인 샘플을 제공하도록 샘플링 알고리즘을 적용해요. 샘플링 비율은 초당 1개 요청과 추가 요청의 5%예요. 함수의 X-Ray 샘플링 비율은 구성할 수 없습니다.
X-Ray에서 trace(추적)는 하나 이상의 service(서비스)가 처리하는 요청에 대한 정보를 기록해요. Lambda는 추적마다 2개의 세그먼트를 기록해서 서비스 그래프에 두 개의 노드를 만들어요. 다음 이미지는 이 두 노드를 강조합니다:

왼쪽의 첫 번째 노드는 호출 요청을 받는 Lambda 서비스를 나타내요. 두 번째 노드는 여러분의 특정 Lambda 함수를 나타냅니다. 다음 예제는 이 두 세그먼트가 있는 추적을 보여줘요. 둘 다 my-function이라는 이름이지만, 하나는 origin이 AWS::Lambda이고 다른 하나는 origin이 AWS::Lambda::Function이에요. AWS::Lambda 세그먼트에 오류가 표시되면 Lambda 서비스에 문제가 있는 것이고, AWS::Lambda::Function 세그먼트에 오류가 표시되면 여러분의 함수에 문제가 있는 거예요.

이 예제는 AWS::Lambda::Function 세그먼트를 펼쳐서 세 개의 하위 세그먼트를 보여줍니다.
참고
AWS는 현재 Lambda 서비스에 변경 사항을 구현하고 있어요. 이 변경으로 인해 AWS 계정의 서로 다른 Lambda 함수가 내보내는 시스템 로그 메시지와 추적 세그먼트의 구조 및 내용에 약간의 차이가 있을 수 있습니다.
여기 표시된 예제 추적은 이전 스타일의 함수 세그먼트를 보여줘요. 이전/새 스타일 세그먼트의 차이는 다음 단락에 설명되어 있죠.
이 변경은 향후 몇 주에 걸쳐 구현되며, 중국 및 GovCloud 리전을 제외한 모든 AWS 리전의 모든 함수가 새 형식의 로그 메시지와 추적 세그먼트로 전환될 예정입니다.
이전 스타일 함수 세그먼트에는 다음 하위 세그먼트가 포함돼요:
- Initialization(초기화) – 함수를 로드하고 초기화 코드를 실행하는 데 걸린 시간을 나타내요. 이 하위 세그먼트는 함수 인스턴스 각각이 처리하는 첫 번째 이벤트에만 나타나요.
- Invocation(호출) – 핸들러 코드를 실행하는 데 걸린 시간을 나타내요.
- Overhead(오버헤드) – Lambda 런타임이 다음 이벤트를 처리할 준비를 하는 데 쓰는 시간을 나타내요.
새 스타일 함수 세그먼트에는 Invocation 하위 세그먼트가 없어요. 대신 고객 하위 세그먼트가 함수 세그먼트에 직접 연결되죠. 이전/새 스타일 함수 세그먼트의 구조에 대해 더 알아보려면 X-Ray 추적 이해를 참고하세요.
HTTP 클라이언트를 계측하고, SQL 쿼리를 기록하고, 주석(annotation)과 메타데이터로 커스텀 하위 세그먼트를 만들 수도 있어요. 자세한 내용은 AWS X-Ray 개발자 안내서의 AWS X-Ray SDK for Python를 참고하세요.
요금
AWS Free Tier의 일부로 매월 일정 한도까지 X-Ray 추적을 무료로 사용할 수 있어요. 그 임계값을 넘으면 X-Ray는 추적 저장과 검색에 요금을 부과해요. 자세한 내용은 AWS X-Ray 요금을 참고하세요.
레이어(layer)에 런타임 의존성 저장 (X-Ray SDK)
X-Ray SDK로 함수 코드의 AWS SDK 클라이언트를 계측하면 배포 패키지가 꽤 커질 수 있어요. 함수 코드를 업데이트할 때마다 런타임 의존성을 다시 업로드하지 않으려면 X-Ray SDK를 Lambda 레이어에 패키징하세요.
다음 예제는 AWS X-Ray SDK for Python을 저장하는 AWS::Serverless::LayerVersion 리소스를 보여줘요.
예제 template.yml – 의존성 레이어
Resources:
function:
Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
Properties:
CodeUri: function/.
Tracing: Active
Layers:
- !Ref libs
...
libs:
Type: [AWS::Serverless::LayerVersion](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-layerversion.html)
Properties:
LayerName: blank-python-lib
Description: Dependencies for the blank-python sample app.
ContentUri: package/.
CompatibleRuntimes:
- python3.11
이 구성에서는 런타임 의존성을 변경할 때만 라이브러리 레이어를 업데이트하면 돼요. 함수 배포 패키지에 코드만 담기므로 업로드 시간을 줄이는 데 도움이 됩니다.
의존성용 레이어를 만들려면 배포 전에 레이어 아카이브를 생성하는 빌드 변경이 필요해요. 작동하는 예제는 blank-python 샘플 애플리케이션을 참고하세요.
더 알아보기 (Learn more)
- Powertools+SAM·CDK 배포, ADOT·X-Ray SDK 계측, 콘솔·API·CloudFormation 활성화, 추적 해석, 의존성 레이어까지 Python 트레이싱 전체 흐름을 다뤄 보세요.