AWS Lambda에서 C# 코드 계측(Instrumenting)

AWS Lambda에서 C# 코드 계측(Instrumenting)

Lambda는 AWS X-Ray와 통합되어 Lambda 애플리케이션을 추적(trace), 디버그, 최적화할 수 있게 도와줘요. X-Ray를 사용하면 애플리케이션의 리소스(Lambda 함수와 다른 AWS 서비스 포함)를 가로지르는 요청을 추적할 수 있죠.

X-Ray로 추적 데이터를 보내려면 다음 세 가지 SDK 라이브러리 중 하나를 사용하면 돼요:

세 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(주제)

출처: AWS Lambda 개발자 안내서

본문

추적을 위해 Powertools for AWS Lambda (.NET)와 AWS SAM 사용

AWS SAM을 사용해 Powertools for AWS Lambda (.NET) 모듈이 통합된 Hello World C# 샘플 애플리케이션을 다운로드하고 빌드하고 배포하려면 아래 단계를 따르세요. 이 애플리케이션은 기본 API 백엔드를 구현하고 로그·메트릭·추적을 내보내기 위해 Powertools를 사용해요. Amazon API Gateway 엔드포인트와 Lambda 함수로 구성되죠. API Gateway 엔드포인트에 GET 요청을 보내면 Lambda 함수가 호출되어 Embedded Metric Format으로 로그와 메트릭을 CloudWatch로 보내고, 추적을 AWS X-Ray로 보냅니다. 함수는 hello world 메시지를 반환해요.

사전 요구 사항

이 섹션의 단계를 완료하려면 다음이 필요해요:

샘플 AWS SAM 애플리케이션 배포

  1. Hello World TypeScript 템플릿으로 애플리케이션을 초기화합니다.

    sam init --app-template hello-world-powertools-dotnet --name sam-app --package-type Zip --runtime dotnet6 --no-tracing
    
  2. 앱을 빌드합니다.

    cd sam-app && sam build
    
  3. 앱을 배포합니다.

    sam deploy --guided
    
  4. 화면의 안내를 따릅니다. 대화형 환경에서 제공되는 기본 옵션을 수락하려면 Enter를 누르세요. 참고
    HelloWorldFunction may not have authorization defined, Is this okay? 에서는 반드시 y를 입력하세요.

  5. 배포된 애플리케이션의 URL을 가져옵니다:

    aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
    
  6. API 엔드포인트를 호출합니다:

    curl {{<URL_FROM_PREVIOUS_STEP>}}
    

    성공하면 다음 응답이 보일 거예요:

    {"message":"hello world"}
    
  7. 함수의 추적을 가져오려면 sam traces를 실행합니다.

    sam traces
    

    추적 출력은 다음과 같아요:

    New XRay Service Graph
      Start time: 2023-02-20 23:05:16+08:00
      End time: 2023-02-20 23:05:16+08:00
      Reference Id: 0 - AWS::Lambda - sam-app-HelloWorldFunction-pNjujb7mEoew - Edges: [1]
       Summary_statistics:
         - total requests: 1
         - ok count(2XX): 1
         - error count(4XX): 0
         - fault count(5XX): 0
         - total response time: 2.814
      Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-pNjujb7mEoew - Edges: []
       Summary_statistics:
         - total requests: 1
         - ok count(2XX): 1
         - error count(4XX): 0
         - fault count(5XX): 0
         - total response time: 2.429
      Reference Id: 2 - (Root) AWS::ApiGateway::Stage - sam-app/Prod - Edges: [0]
       Summary_statistics:
         - total requests: 1
         - ok count(2XX): 1
         - error count(4XX): 0
         - fault count(5XX): 0
         - total response time: 2.839
      Reference Id: 3 - client - sam-app/Prod - Edges: [2]
       Summary_statistics:
         - total requests: 0
         - ok count(2XX): 0
         - error count(4XX): 0
         - fault count(5XX): 0
         - total response time: 0
    
    XRay Event [revision 3] at (2023-02-20T23:05:16.521000) with id (1-63f38c2c-270200bf1d292a442c8e8a00) and duration (2.877s)
     - 2.839s - sam-app/Prod [HTTP: 200]
       - 2.836s - Lambda [HTTP: 200]
     - 2.814s - sam-app-HelloWorldFunction-pNjujb7mEoew [HTTP: 200]
     - 2.429s - sam-app-HelloWorldFunction-pNjujb7mEoew
       - 0.230s - Initialization
       - 2.389s - Invocation
         - 0.600s - ## FunctionHandler
           - 0.517s - Get Calling IP
       - 0.039s - Overhead
    
  8. 이것은 인터넷을 통해 접근 가능한 공개 API 엔드포인트예요. 테스트 후에는 엔드포인트를 삭제하는 걸 권장해요.

    sam delete
    

X-Ray는 애플리케이션에 대한 모든 요청을 추적하진 않아요. X-Ray는 추적이 효율적이면서도 모든 요청의 대표적인 샘플을 제공하도록 샘플링 알고리즘을 적용해요. 샘플링 비율은 초당 1개 요청과 추가 요청의 5%예요. 함수의 X-Ray 샘플링 비율은 구성할 수 없습니다.

X-Ray SDK로 .NET 함수 계측

함수 코드를 계측해 메타데이터를 기록하고 다운스트림 호출을 추적할 수 있어요. 함수가 다른 리소스와 서비스에 하는 호출에 대한 상세 정보를 기록하려면 AWS X-Ray SDK for .NET을 사용하세요. SDK를 얻으려면 프로젝트 파일에 AWSXRayRecorder 패키지를 추가하세요.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.SQSEvents" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="2.1.0" />
    <PackageReference Include="AWSSDK.Core" Version="3.7.103.24" />
    <PackageReference Include="AWSSDK.Lambda" Version="3.7.104.3" />
    <PackageReference Include="AWSXRayRecorder.Core" Version="2.13.0" />
    <PackageReference Include="AWSXRayRecorder.Handlers.AwsSdk" Version="2.11.0" />
  </ItemGroup>
</Project>

AWS SDK, Entity Framework, HTTP 요청에 대한 자동 계측(auto-instrumentation)을 제공하는 다양한 NuGet 패키지가 있어요. 전체 구성 옵션 목록은 AWS X-Ray 개발자 안내서의 AWS X-Ray SDK for .NET을 참고하세요.

원하는 NuGet 패키지를 추가했으면 자동 계측을 구성하세요. 모범 사례는 함수의 핸들러 함수 밖에서 이 구성을 수행하는 거예요. 이렇게 하면 실행 환경 재사용을 활용해 함수 성능이 좋아집니다. 다음 코드 예제에서 RegisterXRayForAllServices 메서드는 함수 생성자에서 호출되어 모든 AWS SDK 호출에 계측을 추가해요.

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function()
    {
        // Add auto instrumentation for all AWS SDK calls
        // It is important to call this method before initializing any SDK clients
        AWSSDKHandler.RegisterXRayForAllServices();
        this._repo = new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request)
    {
        var id = request.PathParameters["id"];
        
        var databaseRecord = await this._repo.GetById(id);
        
        return new APIGatewayProxyResponse 
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = JsonSerializer.Serialize(databaseRecord)
        };
    }
}

Lambda 콘솔로 추적 활성화

콘솔에서 Lambda 함수의 활성 추적(active tracing)을 켜려면 다음 단계를 따르세요.

활성 추적 켜기

  1. Lambda 콘솔의 함수 페이지를 엽니다.
  2. 함수를 선택합니다.
  3. Configuration(구성)을 선택한 다음 Monitoring and operations tools(모니터링 및 운영 도구)를 선택합니다.
  4. Additional monitoring tools(추가 모니터링 도구)에서 Edit(편집)을 선택합니다.
  5. CloudWatch Application Signals and AWS X-Ray 아래에서 Lambda service traces에 대해 Enable(활성화)을 선택합니다.
  6. 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는 애플리케이션에 대한 모든 요청을 추적하진 않아요. X-Ray는 추적이 효율적이면서도 모든 요청의 대표적인 샘플을 제공하도록 샘플링 알고리즘을 적용해요. 샘플링 비율은 초당 1개 요청과 추가 요청의 5%예요. 함수의 X-Ray 샘플링 비율은 구성할 수 없습니다.

X-Ray에서 trace(추적)는 하나 이상의 service(서비스)가 처리하는 요청에 대한 정보를 기록해요. Lambda는 추적마다 2개의 세그먼트를 기록해서 서비스 그래프에 두 개의 노드를 만들어요. 다음 이미지는 이 두 노드를 강조합니다:

단일 함수가 있는 X-Ray 서비스 맵.

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

특정 Lambda 호출의 각 하위 세그먼트별 지연 시간을 보여주는 X-Ray 추적.

이 예제는 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 .NET를 참고하세요.

요금
AWS Free Tier의 일부로 매월 일정 한도까지 X-Ray 추적을 무료로 사용할 수 있어요. 그 임계값을 넘으면 X-Ray는 추적 저장과 검색에 요금을 부과해요. 자세한 내용은 AWS X-Ray 요금을 참고하세요.

더 알아보기 (Learn more)

  • Powertools+SAM 배포, X-Ray SDK 자동 계측, 콘솔·API·CloudFormation 활성화, 추적 해석까지 .NET 트레이싱 전체 흐름을 다뤄 보세요.