Timer ๋ฉ”ํŠธ๋ฆญ ๋“ฑ๋ก ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง (์Šคํ”„๋ง, ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค, ๊ทธ๋ผํŒŒ๋‚˜)

2023. 5. 22. 16:33ใ†์ธํ”„๋Ÿฐ/์Šคํ”„๋ง ๋ถ€ํŠธ - ํ•ต์‹ฌ ์›๋ฆฌ์™€ ํ™œ์šฉ

728x90

 

์นด์šดํ„ฐ ๋ฉ”ํŠธ๋ฆญ ๋“ฑ๋ก ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง (์Šคํ”„๋ง, ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค, ๊ทธ๋ผํŒŒ๋‚˜) (tistory.com)

 

์นด์šดํ„ฐ ๋ฉ”ํŠธ๋ฆญ ๋“ฑ๋ก ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง (์Šคํ”„๋ง, ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค, ๊ทธ๋ผํŒŒ๋‚˜)

์Šคํ”„๋ง & ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค & ๊ทธ๋ผํŒŒ๋‚˜ (๊ทธ๋ผํŒŒ๋‚˜ ์„ค์น˜, ์—ฐ๋™, ์‚ฌ์šฉ ๋ฐฉ๋ฒ•) (tistory.com) ์Šคํ”„๋ง & ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค & ๊ทธ๋ผํŒŒ๋‚˜ (๊ทธ๋ผํŒŒ๋‚˜ ์„ค์น˜, ์—ฐ๋™, ์‚ฌ์šฉ ๋ฐฉ๋ฒ•) ์Šคํ”„๋ง & ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค (์„ค์น˜, ์„ค์ •, ๊ธฐ๋ณธ ๊ธฐ

hyejin.tistory.com

 

 

0๏ธโƒฃ Timer ๋ž€? 

: Timer ๋Š” ์ข€ ํŠน๋ณ„ํ•œ ๋ฉ”ํŠธ๋ฆญ ์ธก์ • ๋„๊ตฌ๋กœ, ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. 

์นด์šดํ„ฐ์™€ ์œ ์‚ฌํ•˜๋ฉฐ, Timer๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‹คํ–‰์‹œ๊ฐ„๋„ ํ•จ๊ป˜ ์ธก์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

seconds_count : ๋ˆ„์  ์‹คํ–‰ ์ˆ˜  (์นด์šดํ„ฐ)

seconds_sum : ์‹คํ–‰ ์‹œ๊ฐ„ ์˜ ํ•ฉ 

seconds_max : ์ตœ๋Œ€ ์‹คํ–‰ ์‹œ๊ฐ„(๊ฐ€์žฅ ์˜ค๋ž˜๊ฑธ๋ฆฐ ์‹คํ–‰ ์‹œ๊ฐ„)  (๊ฒŒ์ด์ง€)  -> ๋‚ด๋ถ€์— ํƒ€์ž„ ์œˆ๋„์šฐ๋ผ๋Š” ๊ฐœ๋…์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— 1 ~ 3 ๋ถ„ ๋งˆ๋‹ค ์ตœ๋Œ€ ์‹คํ–‰ ์‹œ๊ฐ„์ด ๋‹ค์‹œ ๊ณ„์‚ฐ๋œ๋‹ค. 

 

 

1๏ธโƒฃ ๋ฉ”ํŠธ๋ฆญ ๋“ฑ๋ก 3 - Timer 

 

OrderServiceV3 

@Slf4j
public class OrderServiceV3 implements OrderService
{
   private final MeterRegistry meterRegistry;
   private AtomicInteger stock = new AtomicInteger(100);
   
   public OrderServiceV3(MeterRegistry meterRegistry)
   {
      this.meterRegistry = meterRegistry;
   }
   
   @Override
   public void order()
   {
      Timer timer = Timer.builder("my.order")
            .tag("class", this.getClass().getName())
            .tag("method", "order")
            .description("order")
            .register(meterRegistry);
      
      timer.record(() -> {
         log.info("์ฃผ๋ฌธ");
         stock.decrementAndGet();
         sleep(500);
      });
   }
   
   
   @Override
   public void cancel()
   {
      Timer timer = Timer.builder("my.order")
            .tag("class", this.getClass().getName())
            .tag("method", "cancel")
            .description("cancel")
            .register(meterRegistry);
      
      timer.record(() -> {
         log.info("์ทจ์†Œ");
         stock.incrementAndGet();
         sleep(200);
      });
   }
   
   @Override
   public AtomicInteger getStock()
   {
      return stock;
   }
   
   private static void sleep(int l)
   {
      try
      {
         Thread.sleep(l + new Random().nextInt(200));
      }
      catch (InterruptedException e)
      {
         throw new RuntimeException(e);
      }
   }
}

Timer ์ƒ์„ฑํ•˜๊ณ  ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ๋„ Timer์™€ ๋น„์Šทํ•˜๋‹ค. 

Timer.builder(name) ์„ ํ†ตํ•ด์„œ ํƒ€์ด๋จธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  name์— ๋ฉ”ํŠธ๋ฆญ ์ด๋ฆ„์„ ์ง€์ •ํ•ด์ค€๋‹ค. 

tag๋ฅผ ์‚ฌ์šฉํ•ด ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค์—์„œ ํ•„ํ„ฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ ˆ์ด๋ธ”๋กœ ์‚ฌ์šฉ๋œ๋‹ค. -> ์ฃผ๋ฌธ๊ณผ ์ทจ์†Œ๋Š” ๋ฉ”ํŠธ๋ฆญ ์ด๋ฆ„์€ ๊ฐ™๊ณ  tag๋ฅผ ํ†ตํ•ด์„œ ๊ตฌ๋ถ„ํ•˜๋„๋ก ํ•œ๋‹ค. 

register(registry) ๋ฅผ ํ†ตํ•ด ๋งŒ๋“  MeterRegistry์— ๋“ฑ๋กํ•˜๋ฉด ์‹ค์ œ๋กœ ๋“ฑ๋กํ•œ๋‹ค. 

 

Timer๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ์— ํƒ€์ด๋จธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” timer.record()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์•ˆ์— ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ณ  ์‹ถ์€ ๋‚ด์šฉ์„ ํ•จ์ˆ˜๋กœ ํฌํ•จํ•˜๋ฉด ๋œ๋‹ค. 

 

(๊ทธ๋ฆฌ๊ณ  ์ด๋•Œ ์ฃผ๋ฌธ or ์ทจ์†Œํ•  ๋•Œ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ 0.5, 0.2 ์ดˆ ๋Œ€๊ธฐํ•˜๋„๋ก ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ตœ๋Œ€ ์‹คํ–‰์‹œ๊ฐ„์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋žœ๋ค์œผ๋กœ ๊ฐ’์„ ๋”ํ•ด์คฌ๋‹ค. )

 

 

OrderConfigV3

 @Configuration
public class OrderConfigV3
{
   
   @Bean
   OrderService orderService(MeterRegistry meterRegistry)
   {
      return new OrderServiceV3(meterRegistry);
   }
}

 

 

ActuatorApplication 

@Import(OrderConfigV3.class)
@SpringBootApplication(scanBasePackages = "hello.controller")
public class ActuatorApplication {

    public static void main(String[] args) {
        SpringApplication.run(ActuatorApplication.class, args);
    }

}

 

 

* ์‹คํ–‰ 

http://localhost:8080/order

http://localhost:8080/cancel 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒˆ๋กœ ์‹œ์ž‘ํ•˜๋Š”๊ฑฐ๋‹ˆ๊นŒ ์ฃผ๋ฌธ๊ณผ ์ทจ์†Œ๋ฅผ ๋ช‡๋ฒˆ ์‹คํ•ดํ•ด์ฃผ๊ณ  ๋ฉ”ํŠธ๋ฆญ ํ™•์ธํ•˜๋ฉด ๋œ๋‹ค. 

 

http://localhost:8080/actuator/metrics/my.order

COUNT : ๋ˆ„์  ์‹คํ–‰ ์‹œ๊ฐ„ (์นด์šดํ„ฐ) 

TOTAL_TIME : ์‹คํ–‰ ์‹œ๊ฐ„์˜ ํ•ฉ (๊ฐ๊ฐ์˜ ์‹คํ–‰ ์‹œ๊ฐ„ ๋ˆ„์  ํ•ฉ) 

MAX : ์ตœ๋Œ€ ์‹คํ–‰ ์‹œ๊ฐ„ (๊ฐ€์žฅ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ ์‹คํ–‰์‹œ๊ฐ„) 

 

 

* ๊ทธ๋ผํŒŒ๋‚˜ ๋“ฑ๋ก 

 

* ์ฃผ๋ฌธ์ˆ˜ 

 

* ์ตœ๋Œ€ ์‹คํ–‰์‹œ๊ฐ„

 

 

* ํ‰๊ท  ์‹คํ–‰์‹œ๊ฐ„ 

 

 

2๏ธโƒฃ ๋ฉ”ํŠธ๋ฆญ ๋“ฑ๋ก 4 - @Timed 

 

OrderServiceV4

@Timed(value = "my.order")
@Slf4j
public class OrderServiceV4 implements OrderService
{
   private AtomicInteger stock = new AtomicInteger(100);
   
   @Override
   public void order()
   {
      log.info("์ฃผ๋ฌธ");
      stock.decrementAndGet();
      sleep(500);
   }
   
   @Override
   public void cancel()
   {
      log.info("์ทจ์†Œ");
      stock.incrementAndGet();
      sleep(200);
   }
   
   @Override
   public AtomicInteger getStock()
   {
      return stock;
   }
   
   private static void sleep(int l)
   {
      try
      {
         Thread.sleep(l + new Random().nextInt(200));
      }
      catch (InterruptedException e)
      {
         throw new RuntimeException(e);
      }
   }
}

@Timed("my.order") ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ํž˜๋“ค๊ฒŒ(?) ์ฝ”๋“œ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ์‹œ๊ฐ„ ์ธก์ •์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. 

์ด๋•Œ ๊ผญ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ํƒ€์ž…์ด๋‚˜ ๋ฉ”์„œ๋“œ์—๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

(์ง€๊ธˆ์€ ํด๋ž˜์Šค์— ์ ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฒฝ์šฐ์—๋Š” getStock() ์—๋„ ํƒ€์ด๋จธ๊ฐ€ ์ ์šฉ๋œ๋‹ค. )

 

 

OrderConfigV4

 @Configuration
public class OrderConfigV4
{
   @Bean
   OrderService orderService()
   {
      return new OrderServiceV4();
   }
   
   @Bean
   public TimedAspect timedAspect(MeterRegistry meterRegistry)
   {
      return new TimedAspect(meterRegistry);
   }
}

์ „์— @Counted์™€ ๋™์ผํ•˜๊ฒŒ @Timed๋„ TimeAspect๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด AOP๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. 

 

 

ActuatorApplication

@Import(OrderConfigV4.class)
@SpringBootApplication(scanBasePackages = "hello.controller")
public class ActuatorApplication {

    public static void main(String[] args) {
        SpringApplication.run(ActuatorApplication.class, args);
    }
   
}

 

 

* ์‹คํ–‰

http://localhost:8080/actuator/metrics/my.order

 

 

http://localhost:8080/actuator/prometheus

 

 

 

 

 

 

728x90