


io.micrometer:micrometer-registry-prometheus 의존성을 추가하면, Spring Boot Actuator가 제공하는 Metric을 Prometheus Metric 포맷으로 제공한다./actuator/promethues Endpoint가 자동으로 추가된다.dependencies {
    implementation 'io.micrometer:micrometer-registry-prometheus'
}

prometheus.yml 설정 파일에 Application을 등록한다.# 추가
scrape_configs:
  - job_name: "spring-actuator"
    metrics_path: '/actuator/prometheus'
    scrape_interval: 1m
    static_configs:
    - targets:
      - 'localhost:8080'
label 기준으로 필터를 사용할 수 있다.
= : label 값이 일치하는 경우!= : label 값이 일치하지 않는 경우=~ : label 값이 정규식과 일치하는 경우!~ : label 값이 정규식과 일치하지 않는 경우http_server_requests_seconds_count{uri="/actuator/prometheus"}http_server_requests_seconds_count{uri!="/actuator/prometheus", status="200"}http_server_requests_seconds_count{method=~"GET|POST"}http_server_requests_seconds_count{uri!~"/actuator.*"}+-*/%^sum(http_server_requests_seconds_count{outcome="SUCCESS"})sum by (method, status) (http_server_requests_seconds_count)count(http_server_requests_seconds_count)topk(3, http_server_requests_seconds_count)http_server_requests_seconds_count offset 5mhttp_server_requests_seconds_count[5m]increase(http_server_requests_seconds_count{uri="/actuator/prometheus"}[1m])rate(http_server_requests_seconds_count{uri="/actuator/prometheus"}[1m])rate 함수와 유사irate(http_server_requests_seconds_count{uri="/actuator/prometheus"}[1m])
Spring Boot 2.1 System Monitor
jetty_ 를 tomcat_ 으로 변경해야한다.jetty_threads_idle 제거jetty_threads_jobs 제거MeterRegistry 는 자동으로 Bean으로 등록되어 있다.io.micrometer.core.instrument.Counter 를 사용한다.
```java
@RequiredArgsConstructor
public class OrderServiceV1 implements OrderService {
    
    private final MeterRegistry meterRegistry;
    // ...
  
    @Override
    public void order() {
        log.info("OrderServiceV0.order");
        stock.decrementAndGet();
        Counter.builder("my.order")
            .tag("class", this.getClass().getName())
            .tag("method", "order")
            .description("order")
            .register(meterRegistry).increment();
    }
    @Override
    public void cancel() {
        log.info("OrderServiceV0.cancel");
        stock.incrementAndGet();
        Counter.builder("my.order")
            .tag("class", this.getClass().getName())
            .tag("method", "cancel")
            .description("order")
            .register(meterRegistry).increment();
    }
    
    // ...
}
MeterRegistry를 주입받아서 사용한다.CountedAspect Bean으로 등록해야 한다.CountedAspect를 이용해서 AOP를 적용한다.public class OrderServiceV2 implements OrderService {
    // ...
  
    @Counted("my.order")
    @Override
    public void order() {
        log.info("OrderServiceV0.order");
        stock.decrementAndGet();
    }
    @Counted("my.order")
    @Override
    public void cancel() {
        log.info("OrderServiceV0.cancel");
        stock.incrementAndGet();
    }
    
    //...
}
io.micrometer.core.instrument.Timer 를 사용한다.MeterRegistry는 자동으로 Bean으로 등록되어 있다.@RequiredArgsConstructor
public class OrderServiceV1 implements OrderService {
    private final 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("OrderServiceV3.order");
            stock.decrementAndGet();
            sleep(500);
        });
    }
    @Override
    public void cancel() {
        Timer timer = Timer.builder("my.order")
            .tag("class", this.getClass().getName())
            .tag("method", "cancel")
            .description("order")
            .register(meterRegistry);
        timer.record(() -> {
            log.info("OrderServiceV3.cancel");
            stock.incrementAndGet();
            sleep(200);
        });
    }
    //...
}
measurementes 항목을 보면 총 2가지 측정 항목이 추가되었다.COUNT : 호출 횟수TOTAL_TIME : 총 소요 시간MAX : 최대 소요 시간GET http://localhost:8080/actuator/metrics/my.order
{
  "name": "my.order",
  "description": "order",
  "baseUnit": "seconds",
  "measurements": [
    {
      "statistic": "COUNT",
      "value": 11.0
    },
    {
      "statistic": "TOTAL_TIME",
      "value": 4.801505126
    },
    {
      "statistic": "MAX",
      "value": 0.0
    }
  ],
  "availableTags": [
    {
      "tag": "method",
      "values": [
        "cancel",
        "order"
      ]
    },
    {
      "tag": "class",
      "values": [
        "hello.order.v3.OrderServiceV3"
      ]
    }
  ]
}
seconds_count : 누적 실행 수seconds_sum : 총 소요 시간seconds_max : 최대 소요 시간seconds_sum / seconds_count : 평균 실행시간GET http://localhost:8080/actuator/prometheus
# ...
# HELP my_order_seconds order
# TYPE my_order_seconds summary
my_order_seconds_count{class="hello.order.v3.OrderServiceV3",method="order",} 5.0
my_order_seconds_sum{class="hello.order.v3.OrderServiceV3",method="order",} 2.915286917
my_order_seconds_count{class="hello.order.v3.OrderServiceV3",method="cancel",} 6.0
my_order_seconds_sum{class="hello.order.v3.OrderServiceV3",method="cancel",} 1.886218209
# HELP my_order_seconds_max order
# TYPE my_order_seconds_max gauge
my_order_seconds_max{class="hello.order.v3.OrderServiceV3",method="order",} 0.0
my_order_seconds_max{class="hello.order.v3.OrderServiceV3",method="cancel",} 0.0
# ...
TimedAspect Bean으로 등록해야 한다.TimedAspect를 이용해서 AOP를 적용한다.@Timed 메서드 혹은 Class에 적용이 가능하다.public 메서드에 적용된다.io.micrometer.core.instrument.Gauge 를 사용한다.MeterRegistry는 자동으로 Bean으로 등록되어 있다.@Configuration
public class StockConfigV1 {
    @Bean
    public MyStockMetric myStockMetric(OrderService orderService, MeterRegistry meterRegistry) {
        return new MyStockMetric(orderService, meterRegistry);
    }
    @RequiredArgsConstructor
    @Slf4j
    static class MyStockMetric {
        private final OrderService orderService;
        private final MeterRegistry meterRegistry;
        @PostConstruct
        public void init() {
            Gauge.builder("my.stock", orderService, orderService -> {
                    log.info("stock gauge call");
                    return orderService.getStock().get();
                }).description("stock")
                .register(meterRegistry);
        }
    }
}
GET http://localhost:8080/actuator/metrics/my.stock
{
  "name": "my.stock",
  "description": "stock",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 100.0
    }
  ],
  "availableTags": []
}
GET http://localhost:8080/actuator/prometheus
# ...
# HELP my_stock stock
# TYPE my_stock gauge
my_stock 100.0
# ...
io.micrometer.core.instrument.binder.MeterBinder를 Bean으로 등록해서 Gauge 메트릭을 등록할 수 있다.public interface MeterBinder {
    void bindTo(@NonNull MeterRegistry registry);
}
@Configuration
public class StockConfigV2 {
    
    @Bean
    public MeterBinder stockMeterBinder(OrderService orderService) {
        return registry -> Gauge.builder("my.stock", orderService, orderService ->
                orderService.getStock().get())
            .description("stock")
            .register(registry);
    }
}
MeterRegistry 컴포넌트를 통해 Counter, Gauge 등을 등록한다._total 이 붙는다.Timer는 다음과 같은 내용을 한번에 측정한다.seconds_count : 측정 항목의 총 호출 수 - Counterseconds_sum : 측정 항목의 총 소요 시간 - sumseconds_max : 측정 항목의 최대 소요 시간 - Gaugeseconds_sum / seconds_count : 측정 항목의 평균 소요 시간