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 5m
http_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
: 측정 항목의 총 호출 수 - Counter
seconds_sum
: 측정 항목의 총 소요 시간 - sum
seconds_max
: 측정 항목의 최대 소요 시간 - Gauge
seconds_sum
/ seconds_count
: 측정 항목의 평균 소요 시간