스프링 부트 공식 레퍼런스를 한글로 번역한 문서입니다.
전체 목차는 여기에 있습니다.
목차
- 8.6.1. Getting started
- 8.6.2. Supported Monitoring Systems
- 8.6.3. Supported Metrics and Meters
- JVM Metrics
- System Metrics
- Logger Metrics
- Spring MVC Metrics
- Spring WebFlux Metrics
- Jersey Server Metrics
- HTTP Client Metrics
- Tomcat Metrics
- Cache Metrics
- DataSource Metrics
- Hibernate Metrics
- Spring Data Repository Metrics
- RabbitMQ Metrics
- Spring Integration Metrics
- Kafka Metrics
- MongoDB Metrics
- @Timed Annotation Support
- 8.6.4. Registering Custom Metrics
- 8.6.5. Customizing Individual Metrics
- 8.6.6. Metrics Endpoint
8.6. Metrics
스프링 부트 액추에이터는 Micrometer를 위한 의존성 관리와 자동 설정을 제공한다. Micrometer는 다음을 포함한 수많은 모니터링 시스템을 지원하는 애플리케이션 메트릭 파사드다.
- AppOptics
- Atlas
- Datadog
- Dynatrace
- Elastic
- Ganglia
- Graphite
- Humio
- Influx
- JMX
- KairosDB
- New Relic
- Prometheus
- SignalFx
- Simple (인메모리)
- Stackdriver
- StatsD
- Wavefront
8.6.1. Getting started
스프링 부트는 composite MeterRegistry
를 자동 설정하며, 클래스패스에서 지원하는 레지스트리 구현체들을 찾으면 composite에 추가한다. 런타임 클래스패스에 micrometer-registry-{system}
의존성만 있다면 스프링 부트가 레지스트리를 설정해줄 거다.
레지스트리 대부분은 공통 기능을 지원한다. 예를 들어 클래스패스에 특정 Micrometer 레지스트리 구현체가 있어도 해당 레지스트리를 비활성화할 수 있다. 예를 들어 Datadog을 비활성화할 땐:
management.metrics.export.datadog.enabled=false
management:
metrics:
export:
datadog:
enabled: false
아래와 같이 레지스트리 전용 프로퍼티를 따로 명시하지 않으면 모든 레지스트리를 비활성화하게 만들 수도 있다:
management.metrics.export.defaults.enabled=false
management:
metrics:
export:
defaults:
enabled: false
더불어 스프링 부트는 아래처럼 명시해주지 않으면 자동 설정한 모든 레지스트리를 Metrics
클래스에 있는 글로벌 스태틱 composite 레지스트리에 추가한다:
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 토큰을 제공해야 한다:
management.metrics.export.appoptics.api-token=YOUR_TOKEN
management:
metrics:
export:
appoptics:
api-token: "YOUR_TOKEN"
Atlas
기본적으로 로컬에서 실행 중인 Atlas로 메트릭을 익스포트한다. 사용할 Atlas 서버의 위치는 아래와 같이 제공할 수 있다:
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 키를 제공해야 한다:
management.metrics.export.datadog.api-key=YOUR_KEY
management:
metrics:
export:
datadog:
api-key: "YOUR_KEY"
Datadog으로 메트릭을 전송하는 주기도 변경할 수 있다:
management.metrics.export.datadog.step=30s
management:
metrics:
export:
datadog:
step: "30s"
Dynatrace
Dynatrace 레지스트리는 설정한 URI로 메트릭을 주기적으로 푸시한다. 메트릭을 Dynatrace로 익스포트하려면 반드시 API 토큰과 device ID, URI를 제공해야 한다:
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로 메트릭을 전송하는 주기도 변경할 수 있다:
management.metrics.export.dynatrace.step=30s
management:
metrics:
export:
dynatrace:
step: "30s"
Elastic
기본적으로 로컬에서 실행 중인 Elastic으로 메트릭을 익스포트한다. 사용할 Elastic 서버의 위치는 다음 프로퍼티를 통해 제공할 수 있다:
management.metrics.export.elastic.host=https://elastic.example.com:8086
management:
metrics:
export:
elastic:
host: "https://elastic.example.com:8086"
Ganglia
기본적으로 로컬에서 실행 중인 Ganglia로 메트릭을 익스포트한다. 사용할 Ganglia 서버의 호스트와 포트는 아래와 같이 제공할 수 있다:
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 서버의 호스트와 포트는 아래와 같이 제공할 수 있다:
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
를 제공해라. 자체 구현체를 정의하지 않으면 자동 설정한GraphiteConfig
와Clock
빈을 사용한다.
@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 토큰을 제공해야 한다:
management.metrics.export.humio.api-token=YOUR_TOKEN
management:
metrics:
export:
humio:
api-token: "YOUR_TOKEN"
메트릭을 푸시할 데이터소스를 식별하기 위한 태그도 하나 이상 설정해야 한다:
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 서버의 위치는 아래와 같이 제공할 수 있다:
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 도메인으로 메트릭을 익스포트한다. 사용할 도메인은 아래와 같이 제공할 수 있다:
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
를 제공해라. 자체 구현체를 정의하지 않으면 자동 설정한JmxConfig
와Clock
빈을 사용한다.
@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 서버의 위치는 아래와 같이 제공할 수 있다:
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를 제공해야 한다:
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으로 메트릭을 전송하는 주기도 변경할 수 있다:
management.metrics.export.newrelic.step=30s
management:
metrics:
export:
newrelic:
step: "30s"
기본적으로 REST 호출을 통해 메트릭을 게시하지만, Java Agent API가 클래스패스에 있을 땐 Java Agent API를 사용할 수도 있다:
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
빈을 자동 설정한다. 이 빈은 프로메테우스 푸시게이트웨이로 메트릭을 푸시하는 태스크를 관리한다.
PrometheusPushGatewayManager
는 management.metrics.export.prometheus.pushgateway
아래에 있는 프로퍼티로 조정할 수 있다. 다른 것들을 좀 더 커스텀하고 싶으면 자체 PrometheusPushGatewayManager
빈을 제공해도 된다.
SignalFx
SignalFx 레지스트리는 SignalFx로 메트릭을 주기적으로 푸시한다. 메트릭을 SignalFx로 익스포트하려면 반드시 access 토큰을 제공해야 한다:
management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN
management:
metrics:
export:
signalfx:
access-token: "YOUR_ACCESS_TOKEN"
SignalFx로 메트릭을 전송하는 주기도 변경할 수 있다:
management.metrics.export.signalfx.step=30s
management:
metrics:
export:
signalfx:
step: "30s"
Simple
Micrometer는 별다른 레지스트리를 설정하지 않았을때 자동으로 폴백으로 이용하는 간단한 인메모리 백엔드를 함께 제공한다. 덕분에 metrics 엔드포인트에서 어떤 메트릭을 수집하고 있는지 확인할 수 있다.
다른 백엔드를 사용하게 되면 이 인메모리 백엔드는 바로 비활성화된다. 물론 명시적으로 비활성화할 수도 있다:
management.metrics.export.simple.enabled=false
management:
metrics:
export:
simple:
enabled: false
Stackdriver
Stackdriver 레지스트리는 Stackdriver로 메트릭을 주기적으로 푸시한다. 메트릭을 SaaS Stackdriver로 익스포트하려면 반드시 구글 클라우드 프로젝트 id를 제공해야 한다:
management.metrics.export.stackdriver.project-id=my-project
management:
metrics:
export:
stackdriver:
project-id: "my-project"
Stackdriver로 메트릭을 전송하는 주기도 변경할 수 있다:
management.metrics.export.stackdriver.step=30s
management:
metrics:
export:
stackdriver:
step: "30s"
StatsD
StatsD 레지스트리는 UDP를 통해 StatsD 에이전트에 메트릭을 푸시한다. 기본적으로 로컬에서 실행 중인 StatsD 에이전트로 메트릭을 익스포트한다. 사용할 StatsD 에이전트의 호스트, 포트, 프로토콜은 아래와 같이 제공할 수 있다:
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):
management.metrics.export.statsd.flavor=etsy
management:
metrics:
export:
statsd:
flavor: "etsy"
Wavefront
Wavefront 레지스트리는 Wavefront에 메트릭을 주기적으로 푸시한다. 메트릭을 Wavefront로 직접 익스포트하려면 반드시 API 토큰을 제공해야 한다:
management.metrics.export.wavefront.api-token=YOUR_API_TOKEN
management:
metrics:
export:
wavefront:
api-token: "YOUR_API_TOKEN"
아니면 Wavefront 사이드카를 이용하거나, Wavefront API 호스트에 메트릭 데이터를 포워딩하는 내부 프록시를 설정할 수 있다:
management.metrics.export.wavefront.uri=proxy://localhost:2878
management:
metrics:
export:
wavefront:
uri: "proxy://localhost:2878"
Wavefront 프록시에 메트릭을 게시한다면 (문서에 있는 내용 참고) 호스트는 반드시
proxy://HOST:PORT
포맷을 사용해야 한다.
Wavefront로 메트릭을 전송하는 주기도 변경할 수 있다:
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.
로 시작하는 미터 이름을 사용해 게시한다.
다음과 같은 시스템 메트릭을 제공한다:
- CPU 메트릭
- 파일 디스크립터File descriptor 메트릭
- Uptime 메트릭 (애플리케이션을 실행 중인 시간과, 애플리케이션을 기동한 절대 시각을 가리키는 고정 게이지gauge)
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.enabled
를 false
로 설정하고 대신 원하는 곳에만 @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.enabled
를 false
로 설정하고 대신 원하는 곳에만 @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.enabled
를 false
로 설정하고 대신 원하는 곳에만 @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
스프링 부트 액추에이터는 RestTemplate
과 WebClient
의 계측값instrumentation을 관리한다. 이를 활용하려면 자동 설정된 빌더를 주입받아서 인스턴스를 생성해야 한다:
RestTemplate
은RestTemplateBuilder
WebClient
는WebClient.Builder
측정instrumentation을 담당하는 customizer, 이른바 MetricsRestTemplateCustomizer
와 MetricsWebClientCustomizer
를 수동으로 적용할 수도 있다.
기본적으로 이 메트릭은 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} ) |
태그를 커스텀하려면 선택한 클라이언트에 따라 RestTemplateExchangeTagsProvider
나 WebClientExchangeTagsProvider
를 구현한 @Bean
을 등록하면 된다. RestTemplateExchangeTags
와 WebClientExchangeTags
는 간편한 스태틱 함수를 제공한다.
Tomcat Metrics
자동 설정에선 MBeanRegistry
를 활성화했을 때만 톰캣 계측instrumentation을 활성화한다. 기본적으로 MBeanRegistry
는 비활성화돼 있지만, server.tomcat.mbeanregistry.enabled
를 true
로 설정하면 활성화할 수 있다.
톰캣 메트릭은 tomcat.
으로 시작하는 미터 이름을 사용해 게시한다.
Cache Metrics
자동 설정을 이용하면 cache
프리픽스가 달린 메트릭을 통해 기동 시에 사용 가능한 모든 Cache
를 측정instrumentation할 수 있다. 캐시 계측은 기본 메트릭 셋으로 표준화돼 있다. 그밖에 캐시 전용 메트릭도 사용할 수 있다.
지원하는 캐시 라이브러리는 다음과 같다:
- Caffeine
- EhCache 2
- Hazelcast
- 모든 호환 JCache (JSR-107) 구현체
- Redis
이 메트릭엔 캐시 이름과, 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_statistics
를 true
로 설정해야 한다. 아래 프로퍼티를 설정하면 자동 설정된 EntityManagerFactory
에서 통계를 활성화할 수 있다:
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.enabled
를 false
로 설정하고 대신 원하는 곳에만 @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
자동 설정에선, 자동 설정된 컨슈머 팩토리와 프로듀서 팩토리에 각각 MicrometerConsumerListener
와 MicrometerProducerListener
를 등록한다. StreamsBuilderFactoryBean
을 위한 KafkaStreamsMicrometerListener
도 함께 등록한다. 자세한 내용은 스프링 카프카 문서에서 Micrometer Native Metrics 섹션을 참고해라.
MongoDB Metrics
Command Metrics
자동 설정에선, 자동 설정된 MongoClient
에 MongoMetricsCommandListener
를 등록해준다.
내부 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();
}
}
자동 설정되는 커맨드 메트릭을 비활성화하려면 아래 프로퍼티를 설정해라:
management.metrics.mongo.command.enabled=false
management:
metrics:
mongo:
command:
enabled: false
Connection Pool Metrics
자동 설정에선, 자동 설정된 MongoClient
에 MongoMetricsConnectionPoolListener
를 등록해준다.
커넥션 풀에서는 다음과 같은 게이지gauge 메트릭이 만들어진다:
mongodb.driver.pool.size
: 현재 커넥션 풀의 크기와, 유휴 상태인 커넥션, 사용 중인 커넥션mongodb.driver.pool.checkedout
: 현재 사용 중인 커넥션 수mongodb.driver.pool.waitqueuesize
: 현재 풀에서 커넥션을 기다리고 있는 대키 큐 사이즈
각 메트릭에는 기본적으로 다음과 같은 정보를 태그로 추가한다:
Tag | Description |
---|---|
cluster.id |
커넥션 풀에 해당하는 클러스터의 식별자 |
server.address |
커넥션 풀에 해당하는 서버 주소 |
디폴트 메트릭 태그를 대체하려면 다음과 같이 MongoConnectionPoolTagsProvider
빈을 정의해라:
@Configuration(proxyBeanMethods = false)
public class MyConnectionPoolTagsProviderConfiguration {
@Bean
public MongoConnectionPoolTagsProvider customConnectionPoolTagsProvider() {
return new CustomConnectionPoolTagsProvider();
}
}
자동 설정되는 커넥션 풀 메트릭을 비활성화하려면 아래 프로퍼티를 설정해라:
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
운영 환경에서 호스트, 인스턴스, 지역, 스택 등과 같은 차원 정보를 필터링하며 메트릭을 탐색할 땐 보통 공통 태그를 사용한다. 공통 태그는 모든 미터에 적용되며, 다음 예제처럼 설정할 수 있다:
management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod
management:
metrics:
tags:
region: "us-east-1"
stack: "prod"
위 예시에선 모든 미터에 region
과 stack
태그를 추가하며, 각각 us-east-1
, prod
를 값으로 사용한다.
Graphite를 사용할 때는 공통 태그의 순서가 중요하다. 공통 태그를 이렇게 정의하면 순서를 보장할 수 없기 때문에, Graphite 사용자는 이 방법 대신 커스텀
MeterFilter
를 정의하는 게 좋다.
Per-meter Properties
MeterFilter
빈을 사용하는 것 말고도, 프로퍼티를 통해 커스텀 셋을 미터 단위로 제한해서 적용하는 방법도 있다. 미터 단위 커스텀은 ID가 지정한 이름으로 시작하는 모든 미터에 적용된다. 예를 들어, 아래 설정은 example.remote
로 시작하는 ID를 가지고 있는 모든 미터를 비활성화한다:
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.max
가jvm_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).
Next :Auditing
액추에이터의 감사(Audit) 서비스 사용하고 커스텀하기
전체 목차는 여기에 있습니다.