아무거나

[Spring Actuator] Example 3편 - Counter 본문

Java & Kotlin/Spring

[Spring Actuator] Example 3편 - Counter

전봉근 2023. 11. 26. 17:16
반응형

이전글: https://bkjeon1614.tistory.com/782

 

  • Counter (https://micrometer.io/docs/concepts#_counters)
    • 횟수를 세어 metric 으로 제공 단, 자연수만 가능하며 소수나 음수는 불가능하며 일반적으로는 cache hit 에 대한 누적 counter 및 http request 누적 횟수 등과 같이 지금까지 특정 이벤트가 몇 번 발생했는지 누적값을 제공할 때 Counter 를 사용한다. ()
    • 사용법
      • Counter.builder()
        [ApplicationRequestManager.java]
        package com.example.bkjeon.base.actuator.counter;
        
        import io.micrometer.core.instrument.Counter;
        import io.micrometer.core.instrument.MeterRegistry;
        import lombok.RequiredArgsConstructor;
        import org.springframework.stereotype.Service;
        
        import javax.annotation.PostConstruct;
        
        @Service
        @RequiredArgsConstructor
        public class ApplicationRequestManager {
        
            // MeterRegistry 는 기본적으로 Bean 으로 등록되기 때문에 바로 사용하면 된다.
            private final MeterRegistry meterRegistry;
        
            private Counter httpRequestCounter;
        
            @PostConstruct
            void init() {
                httpRequestCounter = Counter.builder("application.http.request").register(meterRegistry);
            }
        
            public void increase() {
                httpRequestCounter.increment();
            }
        
        }      
        
        [CounterController.java]
        package com.example.bkjeon.base.services.api.v1.actuator;
        
        import com.example.bkjeon.base.actuator.counter.ApplicationRequestManager;
        import lombok.RequiredArgsConstructor;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;
        
        @RestController
        @RequestMapping("v1/counter")
        @RequiredArgsConstructor
        public class CounterController {
        
            private final ApplicationRequestManager applicationRequestManager;
        
            @GetMapping("req")
            public String req() {
                applicationRequestManager.increase();
                return "ok";
            }
        
        }      
        
      • /actuator/metrics/application.http.request 에서 확인이 가능하다.
    • Function Counter (https://micrometer.io/docs/concepts#_function_tracking_counters)
      • Counter 의 경우 기존에 만든 횟수 관리 클래스를 재활용하지 못하는 단점이 있어서 Function Counter 를 사용하자.
      • 사용법
        [ApplicationRequestWithoutMicrometer.java]
        package com.example.bkjeon.base.actuator.counter;
        
        import org.springframework.stereotype.Service;
        
        import java.util.concurrent.atomic.AtomicLong;
        
        @Service
        public class ApplicationRequestWithoutMicrometer {
        
            private AtomicLong count = new AtomicLong(0);
        
            public long getCount() {
                return count.get();
            }
        
            public void increase() {
                count.incrementAndGet();
            }
        
        }
        
        [ApplicationFunctionCounterConfig.java]
        package com.example.bkjeon.base.config.actuator;
        
        import com.example.bkjeon.base.actuator.counter.ApplicationRequestWithoutMicrometer;
        import io.micrometer.core.instrument.FunctionCounter;
        import io.micrometer.core.instrument.MeterRegistry;
        import lombok.RequiredArgsConstructor;
        import org.springframework.context.annotation.Configuration;
        
        import javax.annotation.PostConstruct;
        
        @Configuration
        @RequiredArgsConstructor
        public class ApplicationFunctionCounterConfig {
        
            private final ApplicationRequestWithoutMicrometer manager;
            private final MeterRegistry meterRegistry;
        
            @PostConstruct
            void init() {
                FunctionCounter.builder("application.function.counter", manager,
                        ApplicationRequestWithoutMicrometer::getCount).register(meterRegistry);
            }
        
        }
        
        [CounterController.java]
        package com.example.bkjeon.base.services.api.v1.actuator;
        
        import com.example.bkjeon.base.actuator.counter.ApplicationRequestManager;
        import com.example.bkjeon.base.actuator.counter.ApplicationRequestWithoutMicrometer;
        import lombok.RequiredArgsConstructor;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;
        
        @RestController
        @RequestMapping("v1/counter")
        @RequiredArgsConstructor
        public class CounterController {
        
            private final ApplicationRequestManager applicationRequestManager;
            private final ApplicationRequestWithoutMicrometer applicationRequestWithoutMicrometer; // 추가
        
            @GetMapping("req")
            public String req() {
                applicationRequestManager.increase();
                applicationRequestWithoutMicrometer.increase();  // 추가
                return "ok";
            }
        
        }
        
    • MeterBinder 사용
      • FunctionCounter 를 meterRegistry 에 등록하는 방법으로 MeterBinder 를 이용할 수 있다.
        [CounterConfigWithMeterBinder.java]
        package com.example.bkjeon.base.config.actuator;
        
        import com.example.bkjeon.base.actuator.counter.ApplicationRequestWithoutMicrometer;
        import io.micrometer.core.instrument.FunctionCounter;
        import io.micrometer.core.instrument.binder.MeterBinder;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        
        @Configuration
        public class CounterConfigWithMeterBinder {
        
            // MeterBinder 를 이용하면 @PostConstruct 없이 구현이 가능
            @Bean
            public MeterBinder applicationCounterWithMeterBinder(
                    ApplicationRequestWithoutMicrometer manager) {
                return registry -> FunctionCounter.builder("application.function.counter2", manager,
                        ApplicationRequestWithoutMicrometer::getCount).register(registry);
            }
        
        }
        
    • @Counted
      • Micrometer 에서 @Counted 라는 Annotation 을 통해서 AOP 를 제공하고 있다.
      • 예제
        • @Counted 를 사용하려면 AOP 를 사용해야 하므로 build.gradle 에 추가
          [build.gradle]
          dependencies {
              ...
          
              implementation 'org.springframework.boot:spring-boot-starter-aop'        
          }
          
        • 코드적용
          [CountConfig.java]
          package com.example.bkjeon.base.actuator.counter;
          
          import io.micrometer.core.aop.CountedAspect;
          import io.micrometer.core.instrument.MeterRegistry;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          
          @Configuration
          public class CountConfig {
          
              // @Counted 를 사용하기위한 Aspect 등록
              @Bean
              public CountedAspect countedAspect(MeterRegistry meterRegistry) {
                  return new CountedAspect(meterRegistry);
              }
          
          }        
          
          [CounterController.java]
          @RestController
          @RequestMapping("v1/counter")
          @RequiredArgsConstructor
          public class CounterController {        
           
              ...
          
              // @Counted 만 추가하면 된다.
              @Counted("my.counted.counter")
              @GetMapping("req2")
              public String req2() {
                  return "OK";
              }            
          
          }
          
        • http://localhost:9090/api/v1/counter/req2 호출 후 http://localhost:9090/api/actuator/metrics/my.counted.counter 에서 확인

 

참고

- https://semtul79.tistory.com/

 

나는 학생이다

 

semtul79.tistory.com

- https://docs.spring.io/

 

Spring | Home

Cloud Your code, any cloud—we’ve got you covered. Connect and scale your services, whatever your platform.

spring.io

- https://www.inflearn.com/course/spring-boot-actuator-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0/dashboard

반응형
Comments