spring boot/actuator in spring boot

spring boot 3.x + actuator 파헤치기. 7. about metrics endpoint

Hello World Study 2023. 4. 1. 21:32

https://youtu.be/1eS3wFVZsXA

 

actuator 의 수많은 endpoint 중 가장 중요한 endpoint  중 하나가  metrics endpoint  입니다.

 

회사에서 운영/모니터링시 주로 사용하는게 cpu, mem, disk usage, thread count, cache 용량 등인데 이런 정보는 대부분 metrics endpoint 에서 제공되기 때문입니다. 

 

application.yml 에 아래처럼 web 에 모두 노출시키도록 설정 한 후 

management:
  endpoints:
    web:
      exposure:
        include: "*"

 

/actuator/metrics 으로 들어가면 아래처럼 다양한 metric 정보들이 나와 있으며, 

 

나와 있는 metric 이름중 하나를 선택해서 url path 에 넣어주면 해당 이름의 자세한 metric 정보를 알 수 있습니다.

spring  boot 에서는 위와 같이 다양한 metrics 정보를 actuator 를 통해 수집 및 정보를 제공하고 있습니다. 아주 많은 종류가 있기에 중요한 것만 설명을 하겠으며 보다 자세한 내용은 아래 링크를 참고해주세요

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.supported

 

외부 모니터링 시스템과의 연동

actuator 가 cpu, disk, http 등의 metric  정보를 수집해서 web endpoint 로 제공을 하는데, 결국 어딘가에서 이 정보를 읽어서 통합 모니터링 하는데 사용하려는게 목적일 겁니다.

datadog, elastic, prometheus, stackdriver, dynatrace, influx 와 같은 모니터링 연관 시스템에서 metric 정보를 읽어서 해당 시스템 스토리지에 저장하고 grafana와 같은 GUI툴을 통해 시간대별로 metric 값의 변화를 차트로 보여주면 좋을듯 합니다. 

mysql, oracle 등 다양한 RDB가 있고 모두 ansi SQL 이라는 표준 SQL을 지원하나, 각자 다른 SQL 문법도 존재하는걸 알 고 있을겁니다. 모니터링 시스템들도 각자만의 프로토콜로 구현되어 있습니다.

 

  • datadog 에는  json 형태로 metric 정보를 전달해야 하고,
  • elastic 에는 xml 형태로 전달해야 하고,
  • prometheus 에는 json, xml 도 아닌 proemtheus 자체 포맷으로 전달해야 하고,
  • 또 다른 시스템에는 tcp로 데이터를 push해야 할수도 있고,
  • 또 다른 어떤 시스템에는 polling 해야 할수도 있고...

 

와 같이 각자 다른 프로토콜이 있습니다. ( 위의 datadog, elastic , prometheus 의 포맷은 설명을 위해 임의로 적은것입니다. )

 

spring 에서는 actuator 를 통해 이런 다양한 프로토콜과 쉽게 연동이 가능하도록 지원해주고 있습니다. ( actuator 는 metric 부분에 대해서는 micrometer 를 핵심 라이브러리로 사용하므로 정확히는 micrometer 가 이 역할을 수행한다고 봐도 됩니다. )

 

지원되는 외부 모니터링 시스템관련 상세내용은

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.export

이곳을 참고해주세요. 몇가지만 예를 들면 아래와 같습니다.

 

만약 elastic 모니터링 시스템과 연동되어야 한다면 application.yml 에 아래처럼 적어주면 metric 정보를 해당 host로 전달해줍니다. 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.export.elastic

만약 influx DB 와 연동 되고자 한다면 application.yml 에 아래처럼 influx uri 정보를 적어주면 metrics 정보를 influx uri 에 전달해줍니다. 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.export.influx

주의할 것은 일반적인 모니터링 시스템의 경우 spring boot --> 모니터링 시스템 으로 metric 정보를 push 하는데, prometheus 의 경우 prometheus --> spring boot 로 polling 을 한다는 겁니다. 따라서 spring boot 에서는 prometheus 가 polling 할 endpoint 를 설정해야 하며, prometheus 에서는 polling 대상이 되는 spring boot 의 ip, port 및 path 정보를 설정해야 합니다. 

아래 가이드처럼 prometheus 가 설치된 곳의 prometheus.yml 에 spring boot 의 ip, port, path 정보를 적어줘야 합니다. 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.export.prometheus

외부 모니터링 시스템의 설치 및 연동되어 metric 정보를 가져오고 GUI 에서 차트로 보여주는 부분은 이번 시리즈에서는 다루지 않습니다. ( 정보를 수집해서 web endpoint 에 노출하는 것만 해도 작성할 내용이 너무 많네요 ㅡㅜ )

 

외부 모니터링 시스템은 여기까지만 다루기만 하고 다시 metric endpoint 로 돌아가봅시다.

 

MetricsEndpoint

이러한 metric endpoint 는 어떤 클래스가 담당하고 있을까요?

 

endpoint 클래스명들이 상당히 직관적으로 작명되어 있어서  아래처럼 클래스명 찾기팝업에서 metricsendpoint 라고 검색을 하면 됩니다. 다른 예로 info endpoint는 infoendpoint 라고 검색하면 됩니다. health endpoint는 healthendpoint 라고 검색하면 됩니다. 이렇듯 이름이 직관적입니다.

 

이전에 배운대로 @Endpoint 어노테이션으로 metrics 라는 id 를 지정하고 있는 걸로 봐서 제대로 찾은것 같습니다.

@ReadOperation 어노테이션이 붙은 2개 메서드가 있네요.

 

아래 코드에 주석? 으로 달았듯이 하나는 /actuator/metrics  path 에 대한 메서드이며

다른 하나는 /actuator/metrics/{name} 형식의 path 에 대한 메서드입니다. @Selector 어노테이션이 {name}에 해당하는 값을 파라미터로 받아 줍니다.( 이전 포스팅에서 이미 다룬 내용입니다. 가물가물 하나요? ㅡ.ㅡ )

@Endpoint(id = "metrics")
public class MetricsEndpoint {

	private final MeterRegistry registry;

	public MetricsEndpoint(MeterRegistry registry) {
		this.registry = registry;
	}

	@ReadOperation
	public MetricNamesDescriptor listNames() {   <-- /actuator/metrics 용
		Set<String> names = new TreeSet<>();
		collectNames(names, this.registry);
		return new MetricNamesDescriptor(names);
	}

    // /actuator/metrics/{name} 용
	@ReadOperation
	public MetricDescriptor metric(@Selector String requiredMetricName, @Nullable List<String> tag) {
        (생략)
    }

 

동작방식을 확인하기 위해 @ReadOperation 어노테이션이 붙은 메서드에 break point 를 걸고 해당 라인이 실행되도록 http://127.0.0.1:8080/actuator/metrics/disk.free 와 같은 metrics url을 입력해줍니다.

MeterRegistry 에 속한 meter 가 80개나 되는걸 알 수 있습니다. 이중에서 이름 매칭을 통해 적절한 meter 를 찾은 후 거기서 상세정보를 가져오는것이라고 예상할 수 있습니다.

 

MeterRegistry 가 핵심 클래스로 보이는데, 이게 spring 에 속한게 아니라 아래처럼 io.micrometer 에 속한 클래스입니다. 즉 actuator 는 micrometer 가 핵심이고 spring boot은 micrometer 를 spring 에서 사용하기 쉽게 자동 구성 등을 해주는 역할을 하는겁니다.

 

custom metrics 

spring boot 에서는 MeterRegistry 에 meter 를 등록하려면 MeterBinder 를 bean 으로 등록하라고 아래처럼 권고하고 있습니다.

( MeterRegistry 와 동일하게 MeterBinder 도 spring 프로젝트가 아닌 io.micrometer 프로젝트의 클래스입니다.)

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.registering-custom

위 예시가 다소 축약적이고 어려운 문법을 이용하고 있으며 Queue 라는 파라미터에 대한 언급이 없어서 이해가 어려울 수 있습니다. 그래서 제가 조금 풀어서 설명드리겠습니다.

 

재고 관리 시스템용 spring boot 라고 가정을 했을때, 재고 수량은 늘었다 줄었다 할겁니다. 

이걸 metics 에 등록해보도록 하겠습니다. 

 

우선 재고 수량을 리턴해줄수 있는 bean 을 하나 만들어봤습니다.

테스트 용도이니 현재시간을 long 으로 변환한 값을 재고수량이라고 간주합시다. 

@Component
public class MyStockManager {

    public long getStock() {
        // 재고수량을 리턴해야 하지만, 테스트용도이니 현재시간의 long 값을 재고수량으로 대체함.
        return System.currentTimeMillis();
    }
}

이후 아래처럼 재고수량을 제공하는 MeterBinder 를 하나 생성합니다. 해당 MeterBinder 는 위의 MyStockManager 를 필요로 하므로 파라미터로 MyStockManager 을 적어줬습니다. 이러면 bean 으로 만들어질때 MyStockManager  타입의 bean이 주입됩니다.

위 영상의 최종 결과 코드는 아래와 같습니다. IDE의 자동완성을 이용하지 않고 완성된 코드만 보면 이해가 어려우니 위 영상을 통해 구현하는 절차는 확인해보시기 바랍니다.

@Configuration
public class MyStockMeterBinderConfig {

    @Bean
    public MeterBinder myStockMeterBinder(MyStockManager myStockManager) {
        return new MeterBinder() {
            @Override
            public void bindTo(MeterRegistry registry) {
                Gauge.builder("myStockCount", myStockManager, value -> {
                    return value.getStock();
                }).register(registry);

            }
        };
    }
}

결과는 아래와 같습니다. 위의 "myStockCount" 라는 문자열이 path 에 들어갈 문자열과 동일합니다.

Gauge 는 뭔가요? 라고 궁금할 수 있습니다. Gauge 외에 Counter 등 다양한게 있으며, Gauge 가 공식 가이드에 샘플로 나와있어서 저도 동일하게 한것 뿐입니다. 다음 포스팅에서 Gauge, Counter 등 하나씩 살펴볼 예정이니 이런식으로 Meter 를 생성해서 등록하면 되는 구나 정도로 이해하면 됩니다.

 

Micrometer

 

MeterRegistry, MeterBinder 등 핵심 클래스가 모두 spring 이 아닌 micrometer 의 것입니다. 그래서 이제부터는 spring 공식 가이드가 아닌 micrometer  공식 가이드를 참고하여 metric 관련 상세 정보를 살펴보겠습니다.

 

micrometer  의 공식 사이트는 https://micrometer.io 입니다. 이후 아래처럼 가이드 문서로 이동하여 제공되는 meter 들을 확인해볼 수 있습니다.

https://micrometer.io/docs/concepts

 

 

각 meter 들마다 용도와 구현방법이 다르기에 각각에 대해 별도 포스팅으로 가이드하겠습니다.

 

다음 포스팅은 횟수를 측정하는 Counter 라는 metric 에 대해 알아보겠습니다.

 

지금까지 잘 달려오셨습니다. 얼마안남았어요