토리맘의 한글라이즈 프로젝트 logo 토리맘의 한글라이즈 프로젝트

스프링 부트 공식 레퍼런스를 한글로 번역한 문서입니다.

전체 목차는 여기에 있습니다.

목차


8.6. Metrics

스프링 부트 액추에이터는 Micrometer를 위한 의존성 관리와 자동 설정을 제공한다. Micrometer는 다음을 포함한 수많은 모니터링 시스템을 지원하는 애플리케이션 메트릭 파사드다.

Micrometer의 기능에 관한 자세한 내용은 레퍼런스 문서, 그 중에서도 특히 개념 섹션을 참고해라.

8.6.1. Getting started

스프링 부트는 composite MeterRegistry를 자동 설정하며, 클래스패스에서 지원하는 레지스트리 구현체들을 찾으면 composite에 추가한다. 런타임 클래스패스에 micrometer-registry-{system} 의존성만 있다면 스프링 부트가 레지스트리를 설정해줄 거다.

레지스트리 대부분은 공통 기능을 지원한다. 예를 들어 클래스패스에 특정 Micrometer 레지스트리 구현체가 있어도 해당 레지스트리를 비활성화할 수 있다. 예를 들어 Datadog을 비활성화할 땐:

properties yaml
management.metrics.export.datadog.enabled=false
management:
  metrics:
    export:
      datadog:
        enabled: false

아래와 같이 레지스트리 전용 프로퍼티를 따로 명시하지 않으면 모든 레지스트리를 비활성화하게 만들 수도 있다:

properties yaml
management.metrics.export.defaults.enabled=false
management:
  metrics:
    export:
      defaults:
        enabled: false

더불어 스프링 부트는 아래처럼 명시해주지 않으면 자동 설정한 모든 레지스트리를 Metrics 클래스에 있는 글로벌 스태틱 composite 레지스트리에 추가한다:

properties yaml
management.metrics.use-global-registry=false
management:
  metrics:
    use-global-registry: false

레지스트리로 미터를 등록하기 전에 공통 태그를 적용하는 등, 다른 것들을 좀 더 커스텀하고 싶으면 MeterRegistryCustomizer를 구현하는 빈을 원하는 만큼 추가해도 된다:

@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {

    @Bean
    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return (registry) -> registry.config().commonTags("region", "us-east-1");
    }

}

커스텀하고 싶은 레지스트리 구현체가 따로 있다면, 제네릭 타입을 좀 더 구체적으로 지정하면 된다:

@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {

    @Bean
    public MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
        return (registry) -> registry.config().namingConvention(this::name);
    }

    private String name(String name, Meter.Type type, String baseUnit) {
        return ...
    }

}

스프링 부트는 내장 instrumentation 설정도 제공하고 있으며, 이 설정은 설정이나 전용 어노테이션 마커를 통해 제어할 수 있다.

8.6.2. Supported Monitoring Systems

AppOptics

기본적으로 AppOptics 레지스트리는 api.appoptics.com/v1/measurements로 메트릭을 주기적으로 푸시한다. 메트릭을 SaaS AppOptics로 익스포트하려면 반드시 API 토큰을 제공해야 한다:

properties yaml
management.metrics.export.appoptics.api-token=YOUR_TOKEN
management:
  metrics:
    export:
      appoptics:
        api-token: "YOUR_TOKEN"

Atlas

기본적으로 로컬에서 실행 중인 Atlas로 메트릭을 익스포트한다. 사용할 Atlas 서버의 위치는 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.atlas.uri=https://atlas.example.com:7101/api/v1/publish
management:
  metrics:
    export:
      atlas:
        uri: "https://atlas.example.com:7101/api/v1/publish"

Datadog

Datadog 레지스트리는 datadoghq로 메트릭을 주기적으로 푸시한다. 메트릭을 Datadog으로 익스포트하려면 반드시 API 키를 제공해야 한다:

properties yaml
management.metrics.export.datadog.api-key=YOUR_KEY
management:
  metrics:
    export:
      datadog:
        api-key: "YOUR_KEY"

Datadog으로 메트릭을 전송하는 주기도 변경할 수 있다:

properties yaml
management.metrics.export.datadog.step=30s
management:
  metrics:
    export:
      datadog:
        step: "30s"

Dynatrace

Dynatrace 레지스트리는 설정한 URI로 메트릭을 주기적으로 푸시한다. 메트릭을 Dynatrace로 익스포트하려면 반드시 API 토큰과 device ID, URI를 제공해야 한다:

properties yaml
management.metrics.export.dynatrace.api-token=YOUR_TOKEN
management.metrics.export.dynatrace.device-id=YOUR_DEVICE_ID
management.metrics.export.dynatrace.uri=YOUR_URI
management:
  metrics:
    export:
      dynatrace:
        api-token: "YOUR_TOKEN"
        device-id: "YOUR_DEVICE_ID"
        uri: "YOUR_URI"

Dynatrace로 메트릭을 전송하는 주기도 변경할 수 있다:

properties yaml
management.metrics.export.dynatrace.step=30s
management:
  metrics:
    export:
      dynatrace:
        step: "30s"

Elastic

기본적으로 로컬에서 실행 중인 Elastic으로 메트릭을 익스포트한다. 사용할 Elastic 서버의 위치는 다음 프로퍼티를 통해 제공할 수 있다:

properties yaml
management.metrics.export.elastic.host=https://elastic.example.com:8086
management:
  metrics:
    export:
      elastic:
        host: "https://elastic.example.com:8086"

Ganglia

기본적으로 로컬에서 실행 중인 Ganglia로 메트릭을 익스포트한다. 사용할 Ganglia 서버의 호스트와 포트는 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.ganglia.host=ganglia.example.com
management.metrics.export.ganglia.port=9649
management:
  metrics:
    export:
      ganglia:
        host: "ganglia.example.com"
        port: 9649

Graphite

기본적으로 로컬에서 실행 중인 Graphite로 메트릭을 익스포트한다. 사용할 Graphite 서버의 호스트와 포트는 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.graphite.host=graphite.example.com
management.metrics.export.graphite.port=9004
management:
  metrics:
     export:
       graphite:
         host: "graphite.example.com"
         port: 9004

Micrometer는 다차원dimensional 미터 ID를 일차원적인flat 계층형 이름으로 매핑하는 방법을 결정하는 디폴트 HierarchicalNameMapper를 제공한다.

이 동작을 직접 제어하려면 GraphiteMeterRegistry를 정의해 자체 HierarchicalNameMapper를 제공해라. 자체 구현체를 정의하지 않으면 자동 설정한 GraphiteConfigClock 빈을 사용한다.

@Configuration(proxyBeanMethods = false)
public class MyGraphiteConfiguration {

    @Bean
    public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig config, Clock clock) {
        return new GraphiteMeterRegistry(config, clock, this::toHierarchicalName);
    }

    private String toHierarchicalName(Meter.Id id, NamingConvention convention) {
        return ...
    }

}

Humio

기본적으로 Humio 레지스트리는 cloud.humio.com으로 메트릭을 주기적으로 푸시한다. 메트릭을 SaaS Humio로 익스포트하려면 반드시 API 토큰을 제공해야 한다:

properties yaml
management.metrics.export.humio.api-token=YOUR_TOKEN
management:
  metrics:
    export:
      humio:
        api-token: "YOUR_TOKEN"

메트릭을 푸시할 데이터소스를 식별하기 위한 태그도 하나 이상 설정해야 한다:

properties yaml
management.metrics.export.humio.tags.alpha=a
management.metrics.export.humio.tags.bravo=b
management:
  metrics:
    export:
      humio:
        tags:
          alpha: "a"
          bravo: "b"

Influx

기본적으로 로컬에서 디폴트 설정으로 실행 중인 Influx v1 인스턴스로 메트릭을 익스포트한다. 메트릭을 InfluxDB v2로 익스포트하려면 메트릭 작성을 위한 org, bucket, 인증 token을 설정해라. 사용할 Influx 서버의 위치는 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.influx.uri=https://influx.example.com:8086
management:
  metrics:
    export:
      influx:
        uri: "https://influx.example.com:8086"

JMX

Micrometer는 JMX에 계층적인 매핑을 가능하게 해준다. JMX는 주로 로컬에서 쉽게 메트릭을 확인할 수 있는 방법으로, 이식성이 뛰어나다. 기본적으로 metrics JMX 도메인으로 메트릭을 익스포트한다. 사용할 도메인은 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.jmx.domain=com.example.app.metrics
management:
  metrics:
    export:
      jmx:
        domain: "com.example.app.metrics"

Micrometer는 다차원dimensional 미터 ID를 일차원적인flat 계층형 이름으로 매핑하는 방법을 결정하는 디폴트 HierarchicalNameMapper를 제공한다.

이 동작을 직접 제어하려면 JmxMeterRegistry를 정의해 자체 HierarchicalNameMapper를 제공해라. 자체 구현체를 정의하지 않으면 자동 설정한 JmxConfigClock 빈을 사용한다.

@Configuration(proxyBeanMethods = false)
public class MyJmxConfiguration {

    @Bean
    public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock clock) {
        return new JmxMeterRegistry(config, clock, this::toHierarchicalName);
    }

    private String toHierarchicalName(Meter.Id id, NamingConvention convention) {
        return ...
    }

}

KairosDB

기본적으로 로컬에서 실행 중인 KairosDB로 메트릭을 익스포트한다. 사용할 KairosDB 서버의 위치는 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.kairos.uri=https://kairosdb.example.com:8080/api/v1/datapoints
management:
  metrics:
    export:
      kairos:
        uri: "https://kairosdb.example.com:8080/api/v1/datapoints"

New Relic

New Relic 레지스트리는 New Relic으로 메트릭을 주기적으로 푸시한다. 메트릭을 New Relic으로 익스포트하려면 반드시 API 키와 account id를 제공해야 한다:

properties yaml
management.metrics.export.newrelic.api-key=YOUR_KEY
management.metrics.export.newrelic.account-id=YOUR_ACCOUNT_ID
management:
  metrics:
    export:
      newrelic:
        api-key: "YOUR_KEY"
        account-id: "YOUR_ACCOUNT_ID"

New Relic으로 메트릭을 전송하는 주기도 변경할 수 있다:

properties yaml
management.metrics.export.newrelic.step=30s
management:
  metrics:
    export:
      newrelic:
        step: "30s"

기본적으로 REST 호출을 통해 메트릭을 게시하지만, Java Agent API가 클래스패스에 있을 땐 Java Agent API를 사용할 수도 있다:

properties yaml
management.metrics.export.newrelic.client-provider-type=insights-agent
management:
  metrics:
    export:
      newrelic:
        client-provider-type: "insights-agent"

마지막으로, 자체 NewRelicClientProvider 빈을 정의하면 모든 걸 직접 제어할 수 있다.

Prometheus

Prometheus는 개별 애플리케이션 인스턴스를 스크랩하거나 폴링하는 식으로 메트릭을 가져온다. 스프링 부트는 적절한 포맷으로 프로메테우스 스크랩 데이터를 노출해주는 액추에이터 엔드포인트를 제공하는데, /actuator/prometheus에서 이용할 수 있다.

기본 설정에선 이 엔드포인트를 이용할 수 없으며, 사용하려면 반드시 노출해줘야 한다. 자세한 내용은 엔드포인트 노출하기를 참고해라.

다음은 prometheus.yml에 추가하는 scrape_config 예시다:

scrape_configs:
  - job_name: 'spring'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['HOST:PORT']

주기적으로 스크랩할 수 있을 정도로 오래 지속되지 않는 ephemeral job이나 배치 job에서는, 프로메테우스 푸시게이트웨이를 활용하면 프로메테우스에 메트릭을 노출할 수 있다. 프로메테우스 게이트웨이 지원을 활성화하려면 프로젝트에 아래 의존성을 추가해라:

<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient_pushgateway</artifactId>
</dependency>

클래스패스에 프로메테우스 푸시게이트웨이 의존성이 있을 때 management.metrics.export.prometheus.pushgateway.enabled 프로퍼티를 true로 설정하면 PrometheusPushGatewayManager 빈을 자동 설정한다. 이 빈은 프로메테우스 푸시게이트웨이로 메트릭을 푸시하는 태스크를 관리한다.

PrometheusPushGatewayManagermanagement.metrics.export.prometheus.pushgateway 아래에 있는 프로퍼티로 조정할 수 있다. 다른 것들을 좀 더 커스텀하고 싶으면 자체 PrometheusPushGatewayManager 빈을 제공해도 된다.

SignalFx

SignalFx 레지스트리는 SignalFx로 메트릭을 주기적으로 푸시한다. 메트릭을 SignalFx로 익스포트하려면 반드시 access 토큰을 제공해야 한다:

properties yaml
management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN
management:
  metrics:
    export:
      signalfx:
        access-token: "YOUR_ACCESS_TOKEN"

SignalFx로 메트릭을 전송하는 주기도 변경할 수 있다:

properties yaml
management.metrics.export.signalfx.step=30s
management:
  metrics:
    export:
      signalfx:
        step: "30s"

Simple

Micrometer는 별다른 레지스트리를 설정하지 않았을때 자동으로 폴백으로 이용하는 간단한 인메모리 백엔드를 함께 제공한다. 덕분에 metrics 엔드포인트에서 어떤 메트릭을 수집하고 있는지 확인할 수 있다.

다른 백엔드를 사용하게 되면 이 인메모리 백엔드는 바로 비활성화된다. 물론 명시적으로 비활성화할 수도 있다:

properties yaml
management.metrics.export.simple.enabled=false
management:
  metrics:
    export:
      simple:
        enabled: false

Stackdriver

Stackdriver 레지스트리는 Stackdriver로 메트릭을 주기적으로 푸시한다. 메트릭을 SaaS Stackdriver로 익스포트하려면 반드시 구글 클라우드 프로젝트 id를 제공해야 한다:

properties yaml
management.metrics.export.stackdriver.project-id=my-project
management:
  metrics:
    export:
      stackdriver:
        project-id: "my-project"

Stackdriver로 메트릭을 전송하는 주기도 변경할 수 있다:

properties yaml
management.metrics.export.stackdriver.step=30s
management:
  metrics:
    export:
      stackdriver:
        step: "30s"

StatsD

StatsD 레지스트리는 UDP를 통해 StatsD 에이전트에 메트릭을 푸시한다. 기본적으로 로컬에서 실행 중인 StatsD 에이전트로 메트릭을 익스포트한다. 사용할 StatsD 에이전트의 호스트, 포트, 프로토콜은 아래와 같이 제공할 수 있다:

properties yaml
management.metrics.export.statsd.host=statsd.example.com
management.metrics.export.statsd.port=9125
management.metrics.export.statsd.protocol=udp
management:
  metrics:
    export:
      statsd:
        host: "statsd.example.com"
        port: 9125
        protocol: "udp"

사용할 StatsD 라인 프로토콜을 변경할 수도 있다 (디폴트는 Datadog):

properties yaml
management.metrics.export.statsd.flavor=etsy
management:
  metrics:
    export:
      statsd:
        flavor: "etsy"

Wavefront

Wavefront 레지스트리는 Wavefront에 메트릭을 주기적으로 푸시한다. 메트릭을 Wavefront로 직접 익스포트하려면 반드시 API 토큰을 제공해야 한다:

properties yaml
management.metrics.export.wavefront.api-token=YOUR_API_TOKEN
management:
  metrics:
    export:
      wavefront:
        api-token: "YOUR_API_TOKEN"

아니면 Wavefront 사이드카를 이용하거나, Wavefront API 호스트에 메트릭 데이터를 포워딩하는 내부 프록시를 설정할 수 있다:

properties yaml
management.metrics.export.wavefront.uri=proxy://localhost:2878
management:
  metrics:
    export:
      wavefront:
        uri: "proxy://localhost:2878"

Wavefront 프록시에 메트릭을 게시한다면 (문서에 있는 내용 참고) 호스트는 반드시 proxy://HOST:PORT 포맷을 사용해야 한다.

Wavefront로 메트릭을 전송하는 주기도 변경할 수 있다:

properties yaml
management.metrics.export.wavefront.step=30s
management:
  metrics:
    export:
      wavefront:
        step: "30s"

8.6.3. Supported Metrics and Meters

스프링 부트는 다양한 기술과 관련한 미터를 자동으로 등록해준다. 대부분의 경우 특별한 설정이 없어도, 지원하는 모니터링 시스템에 게시할 수 있는 적당한 메트릭을 제공한다.

JVM Metrics

자동 설정에선 코어 Micrometer 클래스들을 사용해서 JVM 메트릭을 활성화한다. 시스템 메트릭은 jvm.으로 시작하는 미터 이름을 사용해 게시한다.

다음과 같은 JVM 메트릭을 제공한다:

System Metrics

자동 설정에선 코어 Micrometer 클래스들을 사용해서 시스템 메트릭을 활성화한다. 시스템 메트릭은 system.process.로 시작하는 미터 이름을 사용해 게시한다.

다음과 같은 시스템 메트릭을 제공한다:

Logger Metrics

자동 설정에선 Logback와 Log4J2를 위한 이벤트 메트릭을 활성화한다. 상세 정보들은 log4j2.events.logback.events.로 시작하는 미터 이름을 사용해 게시한다.

Spring MVC Metrics

자동 설정을 이용하면 스프링 MVC 컨트롤러와 함수형 핸들러로 처리하는 모든 요청을 측정instrumentation할 수 있다. 기본적으로 이 메트릭은 http.server.requests라는 이름으로 만들어진다. 메트릭 이름은 management.metrics.web.server.request.metric-name 프로퍼티를 설정하면 커스텀할 수 있다.

@Controller 클래스와 @RequestMapping 메소드에는 @Timed 어노테이션을 사용할 수 있다 (자세한 내용은 @Timed 어노테이션 지원 참고). 모든 스프링 MVC 요청에서 메트릭을 기록하고 싶지 않다면, management.metrics.web.server.request.autotime.enabledfalse로 설정하고 대신 원하는 곳에만 @Timed 어노테이션을 달아주면 된다.

기본적으로 스프링 MVC와 관련된 메트릭에는 다음과 같은 정보를 태그로 추가한다:

Tag Description
exception 요청을 처리하는 동안 던져진 exception 클래스의 simple name.
method 요청 메소드 (ex. GET, POST)
outcome 응답 상태 코드를 기반으로 만든 요청 결과. 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR다.
status 응답의 HTTP 상태 코드 (ex, 200, 500)
uri 변수(있다면)를 치환하기 이전의 요청 URI 템플릿 (ex. /api/person/{id})

디폴트 태그에 다른 태그도 더 추가하려면 WebMvcTagsContributor를 구현하는 @Bean을 하나 이상 등록해라. 디폴트 태그를 대체하려면 WebMvcTagsProvider를 구현하는 @Bean을 등록해라.

상황에 따라서, 웹 컨트롤러에서 이미 처리한 예외는 요청 메트릭 태그로 기록하지 않는다. 처리한 예외는 요청 속성에 설정해주면, 원하는 예외를 선택해 기록할 수 있다.

Spring WebFlux Metrics

자동 설정을 이용하면 스프링 웹플럭스 컨트롤러와 함수형 핸들러로 처리하는 모든 요청을 측정instrumentation할 수 있다. 기본적으로 이 메트릭은 http.server.requests라는 이름으로 만들어진다. 메트릭 이름은 management.metrics.web.server.request.metric-name 프로퍼티를 설정하면 커스텀할 수 있다.

@Controller 클래스와 @RequestMapping 메소드에는 @Timed 어노테이션을 사용할 수 있다 (자세한 내용은 @Timed 어노테이션 지원 참고). 모든 스프링 웹플럭스 요청에서 메트릭을 기록하고 싶지 않다면, management.metrics.web.server.request.autotime.enabledfalse로 설정하고 대신 원하는 곳에만 @Timed 어노테이션을 달아주면 된다.

기본적으로 스프링 웹플럭스와 관련된 메트릭에는 다음과 같은 정보를 태그로 추가한다:

Tag Description
exception 요청을 처리하는 동안 던져진 exception 클래스의 simple name.
method 요청 메소드 (ex. GET, POST)
outcome 응답 상태 코드를 기반으로 만든 요청 결과. 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR다.
status 응답의 HTTP 상태 코드 (ex, 200, 500)
uri 변수(있다면)를 치환하기 이전의 요청 URI 템플릿 (ex. /api/person/{id})

디폴트 태그에 다른 태그도 더 추가하려면 WebFluxTagsContributor를 구현하는 @Bean을 하나 이상 등록해라. 디폴트 태그를 대체하려면 WebFluxTagsProvider를 구현하는 @Bean을 등록해라.

상황에 따라서, 컨트롤러나 핸들러 펑션에서 이미 처리한 예외는 요청 메트릭 태그로 기록하지 않는다. 처리한 예외는 요청 속성에 설정해주면, 원하는 예외를 선택해 기록할 수 있다.

Jersey Server Metrics

클래스패스에 Micrometer의 micrometer-jersey2 모듈만 있다면, 자동 설정을 이용해 Jersey JAX-RS 구현체로 처리하는 모든 요청을 측정instrumentation할 수 있다. 기본적으로 이 메트릭은 http.server.requests라는 이름으로 만들어진다. 메트릭 이름은 management.metrics.web.server.request.metric-name 프로퍼티를 설정하면 커스텀할 수 있다.

요청을 처리하는 클래스와 메소드에는 @Timed 어노테이션을 사용할 수 있다 (자세한 내용은 @Timed 어노테이션 지원 참고). 모든 Jersey 요청에서 메트릭을 기록하고 싶지 않다면, management.metrics.web.server.request.autotime.enabledfalse로 설정하고 대신 원하는 곳에만 @Timed 어노테이션을 달아주면 된다.

기본적으로 Jersey 서버 메트릭에는 다음과 같은 정보를 태그로 추가한다:

Tag Description
exception 요청을 처리하는 동안 던져진 exception 클래스의 simple name.
method 요청 메소드 (ex. GET, POST)
outcome 응답 상태 코드를 기반으로 만든 요청 결과. 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR다.
status 응답의 HTTP 상태 코드 (ex, 200, 500)
uri 변수(있다면)를 치환하기 이전의 요청 URI 템플릿 (ex. /api/person/{id})

태그를 커스텀하려면 JerseyTagsProvider를 구현한 @Bean을 등록해라.

HTTP Client Metrics

스프링 부트 액추에이터는 RestTemplateWebClient의 계측값instrumentation을 관리한다. 이를 활용하려면 자동 설정된 빌더를 주입받아서 인스턴스를 생성해야 한다:

측정instrumentation을 담당하는 customizer, 이른바 MetricsRestTemplateCustomizerMetricsWebClientCustomizer를 수동으로 적용할 수도 있다.

기본적으로 이 메트릭은 http.client.requests라는 이름으로 만들어진다. 메트릭 이름은 management.metrics.web.client.request.metric-name 프로퍼티를 설정하면 커스텀할 수 있다.

기본적으로 클라이언트로 측정하는 메트릭에는 다음과 같은 정보를 태그로 추가한다:

Tag Description
clientName URI에 있는 호스트
method 요청 메소드 (ex. GET, POST)
outcome 응답 상태 코드를 기반으로 만든 요청 결과. 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR다.
status 가능한 경우 응답의 HTTP 상태 코드 (ex. 200, 500), I/O 이슈가 있을 땐 IO_ERROR, 그외는 CLIENT_ERROR
uri 변수(있다면)를 치환하기 이전의 요청 URI 템플릿 (ex. /api/person/{id})

태그를 커스텀하려면 선택한 클라이언트에 따라 RestTemplateExchangeTagsProviderWebClientExchangeTagsProvider를 구현한 @Bean을 등록하면 된다. RestTemplateExchangeTagsWebClientExchangeTags는 간편한 스태틱 함수를 제공한다.

Tomcat Metrics

자동 설정에선 MBeanRegistry를 활성화했을 때만 톰캣 계측instrumentation을 활성화한다. 기본적으로 MBeanRegistry는 비활성화돼 있지만, server.tomcat.mbeanregistry.enabledtrue로 설정하면 활성화할 수 있다.

톰캣 메트릭은 tomcat.으로 시작하는 미터 이름을 사용해 게시한다.

Cache Metrics

자동 설정을 이용하면 cache 프리픽스가 달린 메트릭을 통해 기동 시에 사용 가능한 모든 Cache를 측정instrumentation할 수 있다. 캐시 계측은 기본 메트릭 셋으로 표준화돼 있다. 그밖에 캐시 전용 메트릭도 사용할 수 있다.

지원하는 캐시 라이브러리는 다음과 같다:

이 메트릭엔 캐시 이름과, CacheManager 빈 이름을 가지고 만드는 이름을 태그로 추가한다.

기동 시에 설정된 캐시만 레지스트리에 바인딩된다. 즉석에서 만들거나 startup phase 이후에 실행하는 코드로 캐시를 생성하는 등, 캐시 설정에 정의되있지 않은 캐시는 따로 등록해줘야 한다. CacheMetricsRegistrar 빈을 이용하면 등록하기 좀 더 쉽다.

DataSource Metrics

자동 설정을 이용하면 jdbc.connections 프리픽스가 달린 메트릭을 통해 사용 가능한 모든 DataSource 객체를 측정instrumentation할 수 있다. 데이터소스를 측정할 땐 현재 커넥션 풀에서 활성 상태인 커넥션, 유휴 상태인 커넥션, 최대/최소로 허용하는 커넥션을 나타내는 게이지gauge를 생성한다.

이 메트릭에는 빈 이름을 가지고 만드는 DataSource의 이름도 태그로 추가한다.

스프링 부트는 지원하는 모든 데이터소스를 위한 메타데이터를 기본으로 제공한다. 원하는 데이터소스가 기본 지원 대상이 아니라면, 별도 DataSourcePoolMetadataProvider 빈을 추가하면 된다. 예제는 DataSourcePoolMetadataProvidersConfiguration을 참고해라.

추가로, Hikari 전용 메트릭은 hikaricp 프리픽스를 통해 노출한다. 각 메트릭에는 풀의 이름을 태그로 추가한다 (spring.datasource.name으로 제어할 수 있다).

Hibernate Metrics

클래스패스에 org.hibernate:hibernate-micrometer가 있으면, 통계를 활성화한 모든 사용 가능한 하이버네이트 EntityManagerFactory 인스턴스를 hibernate라는 메트릭으로 측정instrumentation한다.

이 메트릭에는 빈 이름을 가지고 만드는 EntityManagerFactory의 이름도 태그로 추가한다.

통계를 활성화하려면 반드시 표준 JPA 프로퍼티 hibernate.generate_statisticstrue로 설정해야 한다. 아래 프로퍼티를 설정하면 자동 설정된 EntityManagerFactory에서 통계를 활성화할 수 있다:

properties yaml
spring.jpa.properties[hibernate.generate_statistics]=true
spring:
  jpa:
    properties:
      "[hibernate.generate_statistics]": true

Spring Data Repository Metrics

자동 설정을 이용하면 모든 스프링 데이터 Repository 실행 정보를 측정instrumentation할 수 있다. 기본적으로 이 메트릭은 spring.data.repository.invocations라는 이름으로 만들어진다. 메트릭 이름은 management.metrics.data.repository.metric-name 프로퍼티를 설정하면 커스텀할 수 있다.

Repository 클래스와 메소드에는 @Timed 어노테이션을 사용할 수 있다 (자세한 내용은 @Timed 어노테이션 지원 참고). 모든 Repository를 실행할 때마다 메트릭을 기록하고 싶지 않다면, management.metrics.data.repository.autotime.enabledfalse로 설정하고 대신 원하는 곳에만 @Timed 어노테이션을 달아주면 된다.

기본적으로 레포지토리 실행과 관련된 메트릭에는 다음과 같은 정보를 태그로 추가한다:

Tag Description
repository Repository 클래스의 simple name.
method 실행한 Repository 메소드 이름.
state 결과 상태 (SUCCESS, ERROR, CANCELED, RUNNING).
exception 실행 중에 던져진 exception 클래스의 simple name.

디폴트 태그를 대체하려면 RepositoryTagsProvider를 구현한 @Bean을 등록해라.

RabbitMQ Metrics

자동 설정에선 rabbitmq라는 메트릭을 통해 사용 가능한 모든 RabbitMQ 커넥션 팩토리 계측instrumentation을 활성화한다.

Spring Integration Metrics

Spring Integration은 MeterRegistry 빈만 사용할 수 있다면 자동으로 마이크로미터를 지원한다. 메트릭은 spring.integration.으로 시작하는 미터 이름을 사용해 게시한다.

Kafka Metrics

자동 설정에선, 자동 설정된 컨슈머 팩토리와 프로듀서 팩토리에 각각 MicrometerConsumerListenerMicrometerProducerListener를 등록한다. StreamsBuilderFactoryBean을 위한 KafkaStreamsMicrometerListener도 함께 등록한다. 자세한 내용은 스프링 카프카 문서에서 Micrometer Native Metrics 섹션을 참고해라.

MongoDB Metrics

Command Metrics

자동 설정에선, 자동 설정된 MongoClientMongoMetricsCommandListener를 등록해준다.

내부 MongoDB 드라이버에 커맨드를 발행할 때마다 mongodb.driver.commands라는 이름을 가진 타이머 메트릭이 만들어진다. 각 메트릭에는 기본적으로 다음과 같은 정보를 태그로 추가한다:

Tag Description
command 발행한 커맨드 이름
cluster.id 커맨드를 전송한 클러스터의 식별자
server.address 커맨드를 전송한 서버 주소
status 커맨드 결과 (SUCCESS, FAILED 중 하나)

디폴트 메트릭 태그를 대체하려면 다음과 같이 MongoCommandTagsProvider 빈을 정의해라:

@Configuration(proxyBeanMethods = false)
public class MyCommandTagsProviderConfiguration {

    @Bean
    public MongoCommandTagsProvider customCommandTagsProvider() {
        return new CustomCommandTagsProvider();
    }

}

자동 설정되는 커맨드 메트릭을 비활성화하려면 아래 프로퍼티를 설정해라:

properties yaml
management.metrics.mongo.command.enabled=false
management:
  metrics:
    mongo:
      command:
        enabled: false
Connection Pool Metrics

자동 설정에선, 자동 설정된 MongoClientMongoMetricsConnectionPoolListener를 등록해준다.

커넥션 풀에서는 다음과 같은 게이지gauge 메트릭이 만들어진다:

각 메트릭에는 기본적으로 다음과 같은 정보를 태그로 추가한다:

Tag Description
cluster.id 커넥션 풀에 해당하는 클러스터의 식별자
server.address 커넥션 풀에 해당하는 서버 주소

디폴트 메트릭 태그를 대체하려면 다음과 같이 MongoConnectionPoolTagsProvider 빈을 정의해라:

@Configuration(proxyBeanMethods = false)
public class MyConnectionPoolTagsProviderConfiguration {

    @Bean
    public MongoConnectionPoolTagsProvider customConnectionPoolTagsProvider() {
        return new CustomConnectionPoolTagsProvider();
    }

}

자동 설정되는 커넥션 풀 메트릭을 비활성화하려면 아래 프로퍼티를 설정해라:

properties yaml
management.metrics.mongo.connectionpool.enabled=false
management:
  metrics:
    mongo:
      connectionpool:
        enabled: false

@Timed Annotation Support

io.micrometer.core.annotation 패키지에 들어 있는 @Timed 어노테이션은 위에서 설명했던 몇 가지 지원 기술과 함께 사용할 수 있다. 지원할 때는, 이 어노테이션을 클래스 레벨이나 메소드 레벨에 사용할 수 있다.

예를 들어, 다음은 이 어노테이션을 이용해 @RestController에 있는 모든 요청 매핑을 측정instrument하는 코드다:

@RestController
@Timed
public class MyController {

    @GetMapping("/api/addresses")
    public List<Address> listAddress() {
        return ...
    }

    @GetMapping("/api/people")
    public List<Person> listPeople() {
        return ...
    }

}

단일 매핑만 측정하고 싶다면 클래스 대신 메소드에 어노테이션을 사용하면 된다:

@RestController
public class MyController {

    @GetMapping("/api/addresses")
    public List<Address> listAddress() {
        return ...
    }

    @GetMapping("/api/people")
    @Timed
    public List<Person> listPeople() {
        return ...
    }

}

특정 메소드에서 타이밍 세부 정보를 변경하고 싶을 때는, 클래스 레벨과 메소드 레벨 어노테이션을 결합할 수도 있다:

@RestController
@Timed
public class MyController {

    @GetMapping("/api/addresses")
    public List<Address> listAddress() {
        return ...
    }

    @GetMapping("/api/people")
    @Timed(extraTags = { "region", "us-east-1" })
    @Timed(value = "all.people", longTask = true)
    public List<Person> listPeople() {
        return ...
    }

}

@Timed 어노테이션에 longTask = true를 지정하면 해당 메소드에 LongTaskTimer를 활성화한다. LongTaskTimer에는 별도의 메트릭 이름이 필요하며, 일반 태스크 타이머와 함께 누적해서 사용할 수 있다.

8.6.4. Registering Custom Metrics

커스텀 메트릭을 등록하려면, 아래 예제처럼 원하는 컴포넌트에 MeterRegistry를 주입해라:

@Component
public class MyBean {

    private final Dictionary dictionary;

    public MyBean(MeterRegistry registry) {
        this.dictionary = Dictionary.load();
        registry.gauge("dictionary.size", Tags.empty(), this.dictionary.getWords().size());
    }

}

메트릭이 다른 빈을 의존한다면, 다음 예제처럼 MeterBinder를 사용해서 등록하는 게 좋다:

public class MyMeterBinderConfiguration {

    @Bean
    public MeterBinder queueSize(Queue queue) {
        return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
    }

}

MeterBinder를 이용하면 올바른 의존 관계를 설정할 수 있으며, 메트릭 값을 조회해갈 때 빈을 사용할 수 있다. MeterBinder 구현체는 여러 가지 컴포넌트나 애플리케이션 전반에 걸쳐 메트릭 suite를 반복해서 측정하는 경우에도 유용할 거다.

기본적으로 모든 MeterBinder 빈의 메트릭은 스프링이 관리하는 MeterRegistry에 자동으로 바인딩된다.

8.6.5. Customizing Individual Metrics

특정 Meter 인스턴스를 커스텀해야 한다면 io.micrometer.core.instrument.config.MeterFilter 인터페이스를 이용하면 된다.

예를 들어 ID가 com.example로 시작하는 미터에서 mytag.region이라는 태그명을 mytag.area로 바꾸려면, 다음과 같이 해주면 된다:

@Configuration(proxyBeanMethods = false)
public class MyMetricsFilterConfiguration {

    @Bean
    public MeterFilter renameRegionTagMeterFilter() {
        return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
    }

}

기본적으로 모든 MeterFilter 빈은 스프링이 관리하는 MeterRegistry에 자동으로 바인딩된다. 메트릭을 등록할 땐 스프링이 관리하는 MeterRegistry를 사용해야 하며, Metrics에 있는 스태틱 메소드는 사용하면 안 된다. 이 메소드들은 스프링이 관리하지 않는 글로벌 레지스트리를 사용한다.

Common Tags

운영 환경에서 호스트, 인스턴스, 지역, 스택 등과 같은 차원 정보를 필터링하며 메트릭을 탐색할 땐 보통 공통 태그를 사용한다. 공통 태그는 모든 미터에 적용되며, 다음 예제처럼 설정할 수 있다:

properties yaml
management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod
management:
  metrics:
    tags:
      region: "us-east-1"
      stack: "prod"

위 예시에선 모든 미터에 regionstack 태그를 추가하며, 각각 us-east-1, prod를 값으로 사용한다.

Graphite를 사용할 때는 공통 태그의 순서가 중요하다. 공통 태그를 이렇게 정의하면 순서를 보장할 수 없기 때문에, Graphite 사용자는 이 방법 대신 커스텀 MeterFilter를 정의하는 게 좋다.

Per-meter Properties

MeterFilter 빈을 사용하는 것 말고도, 프로퍼티를 통해 커스텀 셋을 미터 단위로 제한해서 적용하는 방법도 있다. 미터 단위 커스텀은 ID가 지정한 이름으로 시작하는 모든 미터에 적용된다. 예를 들어, 아래 설정은 example.remote로 시작하는 ID를 가지고 있는 모든 미터를 비활성화한다:

properties yaml
management.metrics.enable.example.remote=false
management:
  metrics:
    enable:
      example:
        remote: false

아래 프로퍼티들로 미터 단위 커스텀을 적용할 수 있다:

Property Description
management.metrics.enable 미터가 메트릭을 방출하는 것을 전부 거부할지.
management.metrics.distribution.percentiles-histogram (다른 dimension 간에) 집계할 수 있는 percentile 근사치를 계산하는 데 적합한 히스토그램을 게시할지 여부.
management.metrics.distribution.minimum-expected-value, management.metrics.distribution.maximum-expected-value 미터에서 예상 하는 범위를 고정해서 히스토그램 버킷을 더 적게 게시한다.
management.metrics.distribution.percentiles 애플리케이션 내에서 계산한 percentile 값을 게시한다
management.metrics.distribution.slo 서비스 수준 목표service-level objective에 따라 정의한 버킷을 가지고 있는 누적 히스토그램을 게시한다.

percentiles-histogram, percentiles, slo 뒤에 깔려있는 개념들을 자세히 알고 싶다면 micrometer 문서에서 “Histograms and percentiles” 섹션을 확인해봐라.

8.6.6. Metrics Endpoint

스프링 부트는 애플리케이션에서 수집한 메트릭을 진단할 수 있는 metrics 엔드포인트를 제공한다. 기본 설정에선 이 엔드포인트를 사용할 수 없으며, 사용하려면 반드시 노출해줘야 한다. 자세한 내용은 엔드포인트 노출하기를 참고해라.

/actuator/metrics로 이동하면 사용 가능한 미터 이름들을 확인할 수 있다. 미터 이름을 selector로 제공하면 해당 미터에 관한 정보만 조회할 수 있다 (ex. /actuator/metrics/jvm.memory.max).

여기서 사용하는 이름은 코드에서 사용하는 이름과 일치해야 하며, 모니터링 시스템으로 전달할 때 네이밍 컨벤션에 따라 정규화한 이름을 사용하면 안 된다. 다시 말해, 프로메테우스에선 snake 케이스 컨벤션을 적용해 jvm.memory.maxjvm_memory_max로 나타나지만, metrics 엔드포인트에서 미터를 확인할 땐 jvm.memory.max를 그대로 selector로 사용해야 한다.

또한 URL 뒤에 tag=KEY:VALUE 쿼리 파라미터를 마음껏 추가해서 미터의 dimension을 필터링할 수 있다 (ex. /actuator/metrics/jvm.memory.max?tag=area:nonheap).

여기에서 보이는 측정값들은 미터 이름과 적용해준 태그에 매칭되는 모든 미터들의 통계를 합친 값이다. 따라서 위 예시에서 반환하는 “Value” 통계치는 힙의 “Code Cache”, “Compressed Class Space”, “Metaspace” 영역의 최대 메모리 사용량을 합친 값이다. “Metaspace”의 최대 사이즈만 따로 조회하고 싶다면 tag=id:Metaspace를 추가하면 된다 (ex. /actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace).


전체 목차는 여기에 있습니다.

<< >>

TOP