티스토리 뷰

마이크로미터의 미터 레지스트리

Micrometer는 자바로 제작된 차원형 메트릭 수집 라이브러리로, 대부분의 주요 모니터링 시스템을 지원합니다.

Micrometer에서 Meter는 애플리케이션의 측정 결과를 수집하는 인터페이스이며, 이 측정 결과 각각이 메트릭이 됩니다. MeterRegistry가 이 미터들을 생성하고 보유하며, Micrometer는 다양한 모니터링 시스템에 맞춰 MeterRegistry를 각각 구현하고 있습니다.

Micrometer가 지원하는 레지스트리 구현 라이브러리는 Prometheus, Atlas 등을 포함하며, 메이븐 센트럴과 제이센터에서 다음과 같은 방식으로 사용할 수 있습니다:

io.micrometer:micrometer-registry-<name>

Prometheus용 레지스트리 생성 예시

MeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);

플루언트(fleunt) 빌더를 사용하면 좀 더 세부적인 설정도 가능합니다.

MeterRegistry registry = InfluxMeterRegistry.builder(InfluxConfig.DEFAULT)
    .httpClient(customHttpClient)
    .build();

여러 모니터링 시스템을 사용하는 방법

여러 모니터링 시스템에 메트릭을 동시에 전송하고 싶다면 CompositeMeterRegistry를 사용하면 됩니다:

MeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
MeterRegistry atlasRegistry = new AtlasMeterRegistry(AtlasConfig.DEFAULT);
MeterRegistry compositeRegistry = new CompositeMeterRegistry()
    .add(prometheusRegistry)
    .add(atlasRegistry);
compositeRegistry.counter("my.counter");

레지스트리마다 별도로 미터를 정의할 필요 없이, 하나의 CompositeMeterRegistry에 등록된 모든 레지스트리에 메트릭이 전파됩니다.

MicrometerMeterRegistrySLF4JLoggerFactory와 비슷한 구조를 가지고 있습니다. Logger 인스턴스를 통해 로그를 남기듯, Timer, Counter 같은 측정기를 만들어 메트릭을 기록합니다.

예를 들어, SLF4J에서 LoggerFactory.getLogger(...)로 로그 객체를 가져오듯, Micrometer에서도 Metrics.globalRegistry를 통해 전역 레지스트리에 메트릭을 등록할 수 있습니다.

Timer timer = Timer.builder("time.something")
    .description("time some operation")
    .register(Metrics.globalRegistry);

이렇게 등록한 Timer는 코드 블록의 실행 시간을 마치 로그를 남기듯 자연스럽게 기록할 수 있습니다.

timer.record(() -> {
    logger.info("I did something");
});

의존성 주입 없이도 손쉽게 사용할 수 있어 간단한 컴포넌트나 유틸성 클래스에서 유용합니다.

Micrometer의 레지스트리 구조 이해하기

MicrometerMeterRegistry는 복수의 레지스트리를 조합한 CompositeMeterRegistry로 구성됩니다. 이 구조는 메트릭 데이터를 여러 백엔드(예: Prometheus, Stackdriver 등)로 동시에 전송하기 위해 설계된 것입니다.

Micrometer에서의 레지스트리 흐름을 요약하자면 다음과 같습니다.

  1. 라이브러리에서 정의된 메트릭은 전역 레지스트리에 먼저 등록됩니다.
  2. 애플리케이션에서는 CompositeMeterRegistry를 생성하여 이 전역 레지스트리를 다시 포함합니다.
  3. 이후 PrometheusStackdriver와 같은 개별 구현체 레지스트리를 애플리케이션 레지스트리에 추가합니다.

이 흐름은 다음과 같은 코드 및 다이어그램을 통해 이해할 수 있습니다.

CompositeMeterRegistry composite = new CompositeMeterRegistry();
composite.add(new PrometheusMeterRegistry(...));
composite.add(new StackdriverMeterRegistry(...));

registry-relation

이 구조 덕분에 애플리케이션 내에서 정의한 메트릭은 PrometheusStackdriver 등 여러 모니터링 시스템에 동시에 전달될 수 있습니다.

스프링부트에서의 자동 설정

스프링부트를 사용하는 경우에는 MeterRegistry 설정이 훨씬 더 간편해집니다. micrometer-registry-{system} 형태의 의존성을 클래스패스에 추가하기만 하면, 스프링부트는 해당 레지스트리를 자동으로 감지하고 애플리케이션에 통합해줍니다.

예를 들어 micrometer-registry-prometheus 의존성을 추가하면, 스프링은 자동으로 Prometheus용 레지스트리를 생성하고, 이를 전역 레지스트리에 추가해줍니다. 또한 @Bean으로 설정된 커스텀 레지스트리 역시 전역 레지스트리에 자동 포함됩니다.

이러한 자동 설정 덕분에 개발자는 별도의 수동 등록 없이도 애플리케이션에서 메트릭을 바로 사용할 수 있으며, 설정만으로 PrometheusDatadog 등의 백엔드로 데이터를 전송할 수 있습니다.

댓글