Cloud Platform/AWS

EC2에 AWS X-Ray 적용하기 (2) - AOP, Plugin, Sampling

구티맨 2022. 3. 16. 11:47

목차

    AOP with Spring 적용하기

    AOP 적용 전

    트레이스에서 세부 정보를 확인하면 subsegment가 외부 호출한 부분에 대한 정보만 추적을 하고 있고

    실제 내부에서 호출된 로직들에 대해서는 얼마나 시간이 소요되지는지에 대한 정보가 없습니다.

    그래서 메소드 단위로 시간이 얼마나 소요되는지 확인을 위해 AOP를 적용해보겠습니다.

    설명 링크

     

    먼저 아래의 의존성을 추가해줍니다

     

    <dependency> 
         <groupId>com.amazonaws</groupId> 
         <artifactId>aws-xray-recorder-sdk-spring</artifactId> 
         <version>2.11.0</version> 
    </dependency>

    그리고, AbstractXrayInterceptor 를 상속받아 xrayEnabledClasses 함수를 빈 상태로 오버라이드 하고,

    해당 함수를 적용할 범위를 지정해 줍니다.

    @Pointcut으로 XrayEnabled 어노테이션이 적용된 bean id가 Controller로 끝나는 함수를 범위로 적용하였습니다.

     

    package app.metatron.segment.aws;
    
    import com.amazonaws.xray.entities.Subsegment;
    import com.amazonaws.xray.spring.aop.AbstractXRayInterceptor;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    import java.util.Map;
    
    @Aspect
    @Component
    public class XRayInspector extends AbstractXRayInterceptor {
        @Override
        @Pointcut("@within(com.amazonaws.xray.spring.aop.XRayEnabled) && bean(*Controller)")
        public void xrayEnabledClasses() {}
    }

    컨트롤러에 @XrayEnabled를 선언해주면 AbcController에 aop가 적용되어 Xray 콘솔에서 해당 함수의 호출 콜스택을 확인할 수 있습니다.

    @XRayEnabled
    @Service
    public class AbcController {
        ...
    }

     

    AOP 적용 후

    @XrayEnabled를 선언하는 것이 번거롭다면, 특정 패키지의 모든 빈과 JpaRepository의 모든 함수들에 적용해주어도 됩니다.

    @Pointcut("within(app.example..*) || execution(* org.springframework.data.jpa.repository.JpaRepository+.*(..))")

    서비스 플러그인 설정

    애플리케이션을 호스팅하는 AWS 서비스에 대한 정보를 기록할 수 있게 해 줍니다.

    이전에 작성된 WebConfig의 AWSXrayRecorderBuilder에 withPlugin에 EC2Plugin을 설정해주면 됩니다.

    @Configuration
    public class WebConfig {
    
        static {
            AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin());
    
            builder.withContextMissingStrategy(new LogErrorContextMissingStrategy());
            AWSXRay.setGlobalRecorder(builder.build());
        }
    }

    플러그인 적용 전
    플러그인 적용 후

    위에서 보시는 것처럼 호스팅하고 있는 EC2의 정보를 확인할 수 있습니다.

    샘플링 규칙 적용하기

    샘플링 규칙은 X-Ray 콘솔에서 어떤 요청을 얼마나 기록할지에 대한 규칙을 정의해주는 것을 말합니다.

    Default 규칙은 매 초마다 발생하는 첫 번째 요청과 모든 서비스에 대해 5퍼센트의 요청을 기록합니다.

    X-ray Console Sampling

    콘솔에서 샘플링 규칙을 정의할 수도 있고, SDK가 샘플링 규칙이 정의된 로컬 json파일을 읽어 설정할 수도 있습니다.

    SDK가 로컬 규칙을 이용하는 경우는 X-Ray 샘플링을 이용할 수 없을 때 백업용이나 단독 로컬 규칙으로 사용하기 위해서 사용을 합니다.

    {
      "version": 2,
      "rules": [
        {
          "description": "Player moves.",
          "host": "*",
          "http_method": "*",
          "url_path": "/api/move/*",
          "fixed_target": 0,
          "rate": 0.05
        }
      ],
      "default": {
        "fixed_target": 1,
        "rate": 0.1
      }
    }

    하나의 default 규칙과 하나의 커스텀 규칙을 설정하였습니다.

    default 규칙은 각 초마다 하나의 요청을 추적하고( fixed_target ) 추가로 10 퍼센트의 요청을 추가로 추적합니다( rate ).

    하나의 인스턴스를 사용할 때는 괜찮지만 여러 서비스, 인스턴스를 운영하게 되면 독립적으로 설정하기가 힘들기 때문에 추천하진 않습니다.

     

    로컬 규칙을 적용하기 위해서는 아래와 같이 AWSXrayRecorderBuilder에 샘플링 규칙을 적용하고 이를 GlobalRecorder에 적용해주면 됩니다.

    @Configuration
    public class WebConfig {
    
        static {
            AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin());
    
            URL ruleFile = WebConfig.class.getResource("/aws/sampling-rules.json");
            builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile));
    
            builder.withContextMissingStrategy(new LogErrorContextMissingStrategy());
            AWSXRay.setGlobalRecorder(builder.build());
        }
    
        @Bean
        public Filter TracingFilter(){
            return new AWSXRayServletFilter("Scorekeeper");
        }
    }