본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Document

[SpringBoot] 공식 문서 요약(11) - Actuator 관리

by 김코더 김주역 2022. 1. 16.
반응형

SpringBoot Document Review 11

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/

 

 

 

Actuator

Monitoring and Management over HTTP

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-monitoring.html

 

Monitoring and Management over JMX

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-jmx.html

 

Loggers

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-loggers.html

 

Metrics

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-metrics.html

 

Auditing

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-auditing.html

 

HTTP Tracing

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-http-tracing.html

 

Process Monitoring

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-process-monitoring.html

 

Cloud Foundry Support

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-cloudfoundry.html

 

 

1. Monitoring and Management over HTTP

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-monitoring.html

 

1) 관리용 SSL 설정하기

- 커스텀 port 번호가 설정되면, 다양한 management.server.ssl.* 속성을 사용함으로써 management 서버를 SSL과 함께 구성할 수 있다. 다음 설정 예시는 메인 서버가 HTTPS를 사용하는 동안에 management 서버가 HTTP를 통해 실행될 수 있도록 한다.

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=false

- 메인 서버와 management 서버가 둘다 SSL을 사용하고, 서로 다른 key 저장소를 가지는 경우에는 다음과 같이 설정할 수 있다.

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:management.jks
management.server.ssl.key-password=secret

 

 

2) Management Server 주소 커스터마이징 하기

- 해당 설정은 localhost상에서 유용하다.

management.server.port=8081
management.server.address=127.0.0.1

 

 

3) HTTP Endpoints 비활성화 하기

management.server.port=-1

또는

management.endpoints.web.exposure.exclude=*

 

 

 

2. Monitoring and Management over JMX

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-jmx.html

- JMX(Java Management Extensions)는 애플리케이션을 모니터링하고 관리할 수 있는 표준 매커니즘을 제공한다. 기본적으로, Spring Boot는 management endpoint들을 org.springframework.boot 도메인 아래에서 JMX MBeans들을 노출한다.

- JDK의 bean 디렉토리에 있는 jconsole을 이용하여 MBean, 메모리, 쓰레드 및 클래스의 개수 등을 확인할 수도 있다.

 

1) MBean 이름 커스터마이징 하기

- MBean의 이름은 보통 endpoint의 id로부터 생성된다. 예를 들어, health endpoint는 org.springframework.boot:type, name=Health로써 노출된다.

- 애플리케이션이 하나 이상의 ApplicationContext를 포함한다면 이름이 깨질 수 있다. 이와 같은 문제를 해결하려면, management.endpoints.jmx.unique-names 속성값을 true로 바꿔서 MBean 이름이 항상 unique 상태가 되도록 해야 한다.

- 다음 예시와 같이 unique name과 JMX 도메인을 설정할 수 있다.

spring.jmx.unique-names=true
management.endpoints.jmx.domain=com.example.myapp

 

 

2) JMX Endpoints 비활성화 하기

management.endpoints.jmx.exposure.exclude=*

 

 

3) Jolokia

(1) Jolokia 소개

- Jolokia는 JMX bean들에 접근하는 대안을 제공하는 JMX-HTTP bridge이다.

- Jolokia를 사용하기 위해 다음과 같은 dependency를 추가할 수 있다.

<dependency>
	<groupId>org.jolokia</groupId>
	<artifactId>jolokia-core</artifactId>
</dependency>

- Jolokia endpoint를 노출시키기 위해 manament.endpoints.web.exposure.include 속성값에 jolokia 또는 *를 추가할 수 있다. 이렇게 설정했다면 /actuator/jolokia로 접근할 수 있게 된다.

 

(2) Jolokia 커스터마이징 하기

- 다음과 같이 management.endpoint.jolokia.config.* 속성을 통해 커스터마이징이 가능하다.

management.endpoint.jolokia.config.debug=true

 

(3) Jolokia 비활성화 하기

management.endpoint.jolokia.enabled=false

 

 

 

3. Loggers

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/production-ready-loggers.html

- Spring Boot Actuator은 런타임에서 애플리케이션의 log 레벨을 확인하고 설정하는 기능을 포함한다.

- logger 설정의 전체 혹은 일부를 확인할 수 있다.

- 명시적으로 logging 레벨을 지정하거나, logging framework에 의해 효율적인 logging 레벨을 제공 받을 수도 있다.

- Logging 레벨의 종류 : TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF, null

- 런타임에서 logger 레벨을 바꾸려면, 부분 entity를 해당 logger에 대한 resource URI로 POST 요청을 보내면 된다.

localhost:8080/actuator/loggers/org.springframework.web
{
	"configuredLevel": "DEBUG"
}

※ Logger 레벨을 리셋하고 기본 제공 레벨을 사용하고 싶다면 null 레벨로 요청하면 된다.

 

 

 

4. Metrics

1) Metrics 소개

- Spring Boot Actuator은 dependency 관리와 Micrometer에 대한 자동 설정을 제공한다. Micrometer은 많은 모니터링 시스템들을 지원하는 metrics facade이다.

※ Micrometer 공식 문서 : https://micrometer.io/docs

 

 

2) Metrics 시작하기

- Spring Boot는 composite MeterRegistry를 자동 설정하며, classpath에서 찾을 수 있는 각각의 MeterRegistry 구현체들을 composite에 추가한다.

- 런타임 classpath가 micrometer-registry-{system} dependency를 가지면, Spring Boot가 registry를 설정할 수 있는 충분한 상태가 된다.

- 대부분의 registry들은 공통적인 기능을 가진다. 예를 들어, 어떤 Micrometer registry 구현체가 classpath에 있다면 이 registry를 비활성화할 수도 있다.

management.metrics.export.datadog.enabled=false

※ datadog를 비활성화함.

- 다음과 같은 설정을 통해 명시적으로 거부하지 않는 이상, Spring Boot는 자동 설정된 registry를 Metrics 클래스의 global static composite에 추가할 수 있다.

management.metrics.use-global-registry=false

- Registry에 대한 추가적인 설정을 원한다면 MeterRegistryCustomizer bean을 몇 개든 등록할 수 있다. 아래 예시는 registry로 meter들을 등록하기 전에 공통 태그를 적용한 것이다.

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

- 구체적인 제네릭 타입을 제공해서 커스터마이징한 registry 구현체를 적용할 수 있다.

@Bean
MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
	return registry -> registry.config().namingConvention(MY_CUSTOM_CONVENTION);
}

- Component와 register metrics에 다음과 같이 MeterRegistry를 주입할 수도 있다.

@Component
public class SampleBean {

	private final Counter counter;

	public SampleBean(MeterRegistry registry) {
		this.counter = registry.counter("received.messages");
	}

	public void handleMessage(String message) {
		this.counter.increment();
		// handle message implementation
	}
}

- Spring Boot는 설정이나 전용 어노테이션 marker들을 통해 직접 제어할 수 있는 내장 계측 장치들을 구성해준다.

 

 

3) 지원되는 모니터링 시스템들

(1) AppOptics

- 기본적으로, AppOptics registry는 api.appoptics.com/v1/measurements에 metrics를 주기적으로 push한다.

- Metrics를 SaaS AppOptics에 전달하기 위한 API 토큰이 필요하다.

management.metrics.export.appoptics.api-token=YOUR_TOKEN

 

(2) Atlas

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 Atlas로 전달된다.

- 사용할 Atlas 서버의 위치는 다음과 같이 설정할 수 있다.

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

 

(3) Datadog

- Datadog registry는 datadoghq에 metrics를 주기적으로 push한다.

- Metrics를 Datadog에 전달하기 위한 API 키가 필요하다.

management.metrics.export.datadog.api-key=YOUR_KEY

- Metrics를 Datadog에 전달하는 주기를 설정할 수 있다.

management.metrics.export.datadog.step=30s

 

(4) Dynatrace

- Dynatrace registry는 지정된 URI에 metrics를 주기적으로 push한다.

- Metrics를 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

- Metrics를 Dynatrace에 전달하는 주기를 설정할 수 있다.

management.metrics.export.dynatrace.step=30s

 

(5) Elastic

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 Elastic으로 전달된다.

- 사용할 Elastic 서버의 위치는 다음과 같이 설정할 수 있다.

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

 

(6) Ganglia

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 Ganglia로 전달된다.

- 사용할 Ganglia 서버의 host와 port는 다음과 같이 설정할 수 있다.

management.metrics.export.ganglia.host=ganglia.example.com
management.metrics.export.ganglia.port=9649

 

(7) Graphite

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 Graphite로 전달된다.

- 사용할 Graphite 서버의 host와 port는 다음과 같이 설정할 수 있다.

management.metrics.export.graphite.host=graphite.example.com
management.metrics.export.graphite.port=9004

- Micrometer는 다차원 meter ID가 일차원적인 계층적 이름으로 매핑되는 방식을 결정하는 기본적인 HierarchicalNameMapper를 제공하는데, 이 동작을 직접 제어하려면 별도로 GraphiteMeterRegistry를 정의하고 HierarchicalNameMapper를 따로 만들어서 제공하면 된다. 자동 설정된 GrapiteConfig와 Clock bean은 직접 정의하지 않았다면 기본적으로 제공된다.

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

 

(8) Humio

- 기본적으로, Humio registry는 cloud.humio.com에 metrics를 주기적으로 push한다.

- Metrics를 SaaS Humio에 전달하기 위한 API 토큰이 필요하다.

management.metrics.export.humio.api-token=YOUR_TOKEN

 - Metrics를 push할 data source를 식별하기 위해, 다음과 같이 하나 이상의 태그를 설정해야 한다.

management.metrics.export.humio.tags.alpha=a
management.metrics.export.humio.tags.bravo=b

 

(9) Influx

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 Influx으로 전달된다.

- 사용할 Influx 서버의 위치는 다음과 같이 설정할 수 있다.

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

 

(10) JMX

- Micrometer은 metrics를 로컬에서 볼 수 있도록, 저렴하고 이식성 높은 방식으로 JMX로의 계층적인 매핑을 제공해준다.

- 기본적으로, metrics는 metrics JMX 도메인으로 전달되며, 사용할 도메인은 다음과 같이 설정할 수 있다.

management.metrics.export.jmx.domain=com.example.app.metrics

- Micrometer는 다차원 meter ID가 일차원적인 계층적 이름으로 매핑되는 방식을 결정하는 기본적인 HierarchicalNameMapper를 제공하는데, 이 동작을 직접 제어하려면 별도로 JmxMeterRegistry를 정의하고 HierarchicalNameMapper를 따로 만들어서 제공하면 된다. 자동 설정된 JmxConfig와 Clock bean은 직접 정의하지 않았다면 기본적으로 제공된다.

 

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

 

(11) KairosDB

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 KairosDB로 전달된다.

- 사용할 KairosDB 서버의 위치는 다음과 같이 설정할 수 있다.

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

 

(12) New Relic

- New Relic registry는 New Relic에 metrics를 주기적으로 push한다.

- Metrics를 New Relic에 전달하기 위한 API 키와 계정 ID가 필요하다.

management.metrics.export.newrelic.api-key=YOUR_KEY
management.metrics.export.newrelic.account-id=YOUR_ACCOUNT_ID

- Metrics를 New Relic에 전달하는 주기를 설정할 수 있다.

 

management.metrics.export.newrelic.step=30s

 

(13) Prometheus

- Prometheus는 metrics의 각 app 인스턴스를 스크랩하거나 폴링한다.

- Spring Boot는 적절한 포맷으로 Prometheus 스크랩이 가능한 actuator endpoint를 제공해주는데, 이 endpoint는 /actuator/prometheus에서 확인할 수 있다.

- Prometheus endpoint는 기본적으로 비활성화되어 있기 때문에 노출 설정이 이루어져야 한다.

- 다음은 prometheus.yml에 추가할 수 있는 scrape_config 설정 예시이다.

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

- 스크랩하기 충분할 정도로 오래 지속되지 않는 batch 작업이나 수명이 짧은 작업들에 대하여, metrics를 Prometheus에 노출할 수 있도록 Prometheus Pushgateway의 지원을 받을 수 있다.

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

- Prometheus Pushgateway dependency가 classpath에 있다면, Spring Boot는 PrometheusPushGatewayManager bean을 자동 설정한다. 이는 metrics가 Prometheus Pushgateway로 push되는 것을 관리한다. PrometheusPushGatewayManager는 management.metrics.export.prometheus.pushgateway 속성 아래에서 조정할 수 있으며, 추가적인 설정을 원한다면 별도로 PrometheusPushGatewayManager bean을 만들어서 제공해도 된다.

 

(14) SignalFx

- SignalFx registry는 SignalFx에 metrics를 주기적으로 push한다.

- Metrics를 SignalFx에 전달하기 위한 API 토큰이 필요하다.

management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN

- Metrics를 SignalFx에 전달하는 주기를 설정할 수 있다.

management.metrics.export.signalfx.step=30s

 

(15) Simple

- Micrometer은 다른 registry가 설정되지 않았다면, fall back으로 자동으로 사용될 수 있는 인메모리 backend를 제공한다. 그래서, metircs endpoint에서 어떤 metric들이 수집되는지 확인할 수 있게 된다.

※ Fall back : 시스템 전체가 고장나는 것을 극복하는 수법이다. 예를 들면 컴퓨터 장치의 일부 고장이 발생했으면 그 부분을 전부 또는 일부분만 교환하거나 혹은 수동 등으로 서비스 기능을 저하시키면서라도 가동시킨다.

- 이 인메모리 backend는 우리가 다른 backend를 사용하게 되면 비활성화 된다. 다음과 같은 설정으로 simple을 명시적으로 비활성화시킬 수도 있다.

management.metrics.export.simple.enabled=false

 

(16) StatsD

- StatsD registry는 metrics를 UDP 방식을 통해 StatsD 에이전트로 push한다.

- 기본적으로, metrics는 우리의 로컬 머신에서 실행되는 StatsD 에이전트로 전달된다.

- 사용할 StatsD 에이전트의 host와 port는 다음과 같이 설정할 수 있다.

management.metrics.export.statsd.host=statsd.example.com
management.metrics.export.statsd.port=9125

- 다음과 같은 설정으로 StatsD line 프로토콜을 지정할 수 있다. 기본값은 Datadog이다.

management.metrics.export.statsd.flavor=etsy

 

(17) Wavefront

- Wavefront registry는 Wavefront에 metrics를 주기적으로 push한다.

- Metrics를 Wavefront에 전달하기 위한 API 토큰이 필요하다.

management.metrics.export.wavefront.api-token=YOUR_API_TOKEN

- Wavefront sidecar을 사용하거나, metrics 데이터를 Wavefront API 호스트로 보내는 환경에 설정되어 있는 내부 proxy를 사용하는 방법도 있다.

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

※ Metrics를 Wavefront proxy로 보낼 때는 proxy://HOST:PORT 형식을 지켜야 한다.

- Metrics를 Wavefront에 전달하는 주기를 설정할 수 있다.

management.metrics.export.wavefront.step=30s

 

 

4) 지원되는 Metrics

(1) Spring Boot가 등록해주는 코어 metrics

- JVM metrics : 다양한 메모리와 버퍼 풀, garbage 컬렉션 관련 통계, Threads, loaded/unloaded 클래스의 개수 정보

- CPU metrics

- File descriptor metrics

- Kafka consumer metrics

- Log4j2 metrics : 각 레벨별로 Log4j2에 기록되어 있는 이벤트의 수를 기록

- Logback metrics : 각 레벨별로 Logback에 기록되어 있는 이벤트의 수를 기록

- Uptime metrics : 애플리케이션의 실행 시간에 대한 측정과 애플리케이션의 시작 시점에 대한 측정을 보고

- Tomcat metrics

- Spring Integration metrics

 

(2) Spring MVC Metrics

- 자동 설정은 Spring MVC에 의해 처리되는 요청들에 대한 계측을 활성화해준다.

- management.metrics.web.server.auto-time-requests 속성값이 true이면 모든 요청에 대한 측정이 이루어지는데, false로 되어있더라도 @Timed 어노테이션을 요청 처리 메소드에 추가함으로써 측정을 활성화할 수 있다.

@RestController
@Timed // 컨트롤러의 모든 요청 핸들러에 대하여 타이밍을 활성화하도록 지정함
public class MyController {

	@GetMapping("/api/people")
	@Timed(extraTags = { "region", "us-east-1" })  // 각 endpoint를 활성화하도록 지정함. 클래스에 이미 설정되어 있다면 생략해도 무방하지만, 특정 endpoint의 타이밍에 추가적인 커스터마이징을 할 수 있다.
	@Timed(value = "all.people", longTask = true) // longTask를 true로 설정하면 해당 메소드에 loag task 타이머를 설정한다. Long task 타이머는 개별적인 metric 이름이 요구된다.
	public List<Person> listPeople() { ... }
}

- 기본적으로, metrics는 "http.server.requests" 라는 이름으로 생성된다. 이름을 커스터마이징하려면 management.metrics.web.server.requests-metric-name 속성을 사용하면 된다.

- 기본적으로, Spring MVC 관련 metrics는 다음과 같은 정보가 태그된다.

<1> method : GET 또는 POST와 같은 요청 메소드

<2> uri : 변수 치환 이전의 URI - 예) /api/person/{id}

<3> status : HTTP 상태 코드

<4> exception : 요청을 처리하는동안 발생할 수 있는 예외의 간단한 클래스 이름

<5> outcome : 응답의 상태 코드에 기반한 요청의 결과 - 예) 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR

※ 태그들을 커스터마이징 하려면, WebMvbTagsProvider 구현체를 @Bean으로 등록한다.

 

(3) Spring WebFlux Metrics

- 자동 설정은 WebFlux 컨트롤러 또는 함수형 핸들러에 의해 처리되는 모든 요청들에 대한 계측을 활성화해준다.

- 기본적으로, metrics는 "http.server.requests" 라는 이름으로 생성된다. 이름을 커스터마이징하려면 management.metrics.web.server.requests-metric-name 속성을 사용하면 된다.

- 기본적으로, WebFlux 관련 metrics는 다음과 같은 정보가 태그된다.

<1> method : GET 또는 POST와 같은 요청 메소드

<2> uri : 변수 치환 이전의 URI - 예) /api/person/{id}

<3> status : HTTP 상태 코드

<4> exception : 요청을 처리하는동안 발생할 수 있는 예외의 간단한 클래스 이름

<5> outcome : 응답의 상태 코드에 기반한 요청의 결과 - 예) 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR

※ 태그들을 커스터마이징 하려면, WebFluxTagsProvider 구현체를 @Bean으로 등록한다.

 

(4) Jersey Server Metrics

- Micrometer의 micrometer-jersey2 모듈이 classpath에 있다면, 자동 설정은 Jersey JAX-RS 구현체에 의해 처리되는 요청들에 대한 계측을 활성화해준다.

- management.metrics.web.server.auto-time-requests 속성값이 true이면 모든 요청에 대한 측정이 이루어지는데, false로 되어있더라도 @Timed 어노테이션을 요청 처리 메소드에 추가함으로써 측정을 활성화할 수 있다.

@Component
@Path("/api/people")
@Timed // resource의 모든 요청 핸들러에 대하여 타이밍을 활성화하도록 지정함
public class Endpoint {

	@GET
	@Timed(extraTags = { "region", "us-east-1" })  // 각 endpoint를 활성화하도록 지정함. 클래스에 이미 설정되어 있다면 생략해도 무방하지만, 특정 endpoint의 타이밍에 추가적인 커스터마이징을 할 수 있다.
	@Timed(value = "all.people", longTask = true) // longTask를 true로 설정하면 해당 메소드에 loag task 타이머를 설정한다. Long task 타이머는 개별적인 metric 이름이 요구된다.
	public List<Person> listPeople() { ... }
}

- 기본적으로, metrics는 "http.server.requests" 라는 이름으로 생성된다. 이름을 커스터마이징하려면 management.metrics.web.server.requests-metric-name 속성을 사용하면 된다.

- 기본적으로, WebFlux 관련 metrics는 다음과 같은 정보가 태그된다.

<1> method : GET 또는 POST와 같은 요청 메소드

<2> uri : 변수 치환 이전의 URI - 예) /api/person/{id}

<3> status : HTTP 상태 코드

<4> exception : 요청을 처리하는동안 발생할 수 있는 예외의 간단한 클래스 이름

<5> outcome : 응답의 상태 코드에 기반한 요청의 결과 - 예) 1xx는 INFORMATIONAL, 2xx는 SUCCESS, 3xx는 REDIRECTION, 4xx는 CLIENT_ERROR, 5xx는 SERVER_ERROR

※ 태그들을 커스터마이징 하려면, JerseyTagsProvider 구현체를 @Bean으로 등록한다.

 

5) HTTP Client Metrics

- Spring Boot Actuator은 RestTemplate, WebClient의 계측을 관리해준다. 이를 위해 우리는 자동 설정된 빌더를 주입 받고, 이 빌더를 통해 인스턴스를 생성해야 한다. RestTemplate에 대한 빌더는 RestTemplateBuilder이고, WebClient에 대한 빌더는 WebClient.Builder이다.

- 계측 역할을 하는 커스터마이저인 MetricsRestTemplateCustomizer와 MetricsWebClientCustomizer를 적용할 수도 있다.

- 기본적으로, metrics는 "http.server.requests" 라는 이름으로 생성된다. 이름을 커스터마이징하려면 management.metrics.web.server.requests-metric-name 속성을 사용하면 된다.

- 기본적으로, 측정된 클라이언트로 생성되는 metrics는 다음과 같은 정보가 태그된다.

<1> method : GET 또는 POST와 같은 요청 메소드

<2> uri : 변수 치환 이전의 URI - 예) /api/person/{id}

<3> status : HTTP 상태 코드

<4> clientName : URI의 host부분

※ 선택한 클라이언트에 기반하여 이 태그들을 커스터마이징 하려면, RestTemplateExchangeTagsProvider 또는 WebClientExchangeTagsProvider 구현체를 @Bean으로 등록한다. RestTemplateExchangeTags와 WebClientExchangeTags에는 편리한 static 함수들이 있다.

 

(6) Cache Metrics

- 자동 설정은 "cache" prefix가 붙은 metrics를 통해서, 기동 시에 사용 가능한 모든 Cache들에 대한 계측을 가능하게 해준다.

- Cache 계측은 기본 metrics 집합에 표준화되어 있으며, cache 전용 metric들도 존재한다.

- 지원되는 캐시 라이브러리들로는 Caffeine, EhCache 2, Hazelcast가 있고, 호환되는 모든 JCache (JSR-107) 구현체들도 지원된다.

- Metrics는 캐시의 이름과 CacheManager의 이름으로 태그되는데, CacheManager의 이름은 bean의 이름으로부터 유도된다. 

- 기동 시에 설정되는 캐시들만 registry에 바인딩된다. 캐시 설정에 정의되지 않은 캐시들(급하게 생성된 캐시, startup 구절 이후에 프로그래밍적으로 생성된 캐시)은 명시적인 등록이 필요하다. 이러한 등록 과정은 CacheMetricsRegistrar bean을 사용하면 쉬워진다.

 

(7) DataSource Metrics

- 자동 설정은 "jdbc.connections" prefix가 붙은 metrics를 통해서, 사용 가능한 모든 DataSource 객체들에 대한 계측을 가능하게 해준다.

- Data source 계측의 결과는 커넥션 풀에서의 현재 활성 상태, 최대/최소 허용 연결 수를 표시해주는 게이지로 나타난다.

- Metrics는 bean의 이름을 기반으로 계산된 DataSource의 이름으로 태그된다.

- 기본적으로, Spring Boot는 지원되는 모든 data source들에 대한 메타 데이터를 제공한다. 만약 원하는 data source가 지원되지 않는다면, 추가적인 DataSourcePoolMetadataProvider bean을 추가할 수 있다. 이와 관련된 예시로 DataSourcePoolMetadataProvidersConfiguration을 참고하면 좋다.

- "hikaricp" prefix를 통하여 hikari 전용 metrics도 노출시킬 수 있다. 각 metric은 Pool의 이름으로 태그되며, spring.datasource.name 속성으로 제어할 수 있다.

 

(8) Hibernate Metrics

- 자동 설정은 사용 가능한 모든 Hibernate EntityManagerFactory 인스턴스들에 대한 계측을 가능하게 해준다.

- EntityManagerFactory는 hibernate라는 metric으로 측정되는 통계를 제공한다.

- 자동 설정된 EntityManagerFactory에서 통계를 활성화 하려면, 표준 JPA 속성인 hibernate.generate_statistics 속성값이 true로 설정되어 있어야 한다.

spring.jpa.properties.hibernate.generate_statistics=true

- Metrics는 EntityManagerFactory의 이름으로 태그되는데, EntityManagerFactory의 이름은 bean의 이름으로부터 유도된다.

 

(9) RabbitMQ Metrics

- 자동 설정은 rabbitmq라는 metric을 통해서, 사용 가능한 모든 RabbitMQ connection factory들에 대한 계측을 가능하게 해준다.

 

 

5) Custom metrics 등록하기

- Custom metrics를 등록하려면, 컴포넌트에 MeterRegistry를 주입받아서 사용하면 된다.

@Component
public class Dictionary {

	private final List<String> words = new CopyOnWriteArrayList<>();

	Dictionary(MeterRegistry registry) {
		registry.gaugeCollectionSize("dictionary.size", Tags.empty(), this.words);
	}

	// …
}

- 컴포넌트 또는 애플리케이션에 걸쳐 metrics suite(모임, 군)를 반복적으로 계측하는 경우에는 이 suite를 MeterBinder 구현체에 캡슐화할 수 있다. 기본적으로, 모든 MeterBinder bean들에 대한 metrics는 자동으로 Spring에서 관리되는 MeterRegistry로 바인딩 된다.

 

 

6) 각 metric들을 커스터마이징 하기

(1) MeterFilter

- 특정 Meter 인스턴스를 커스터마이징하기 위해 io.micrometer.core.instrument.config.MeterFilter 인터페이스를 사용할 수 있다.

- 기본적으로, 모든 MeterFilter bean들은 자동으로 micrometer MeterRegistry.Config에 적용된다.

- 다음 예제는 com.example로 시작하는 모든 meter ID들에 대하여 "mytag.region"라는 태그 이름을 "mytag.area"로 변경하는 코드이다.

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

 

(2) 공통 태그들

- 공통 태그들은 호스트, 인스턴스, 지역, 스택과 같은 운영 환경에서 차원적 drill-down으로 활용된다.

※ drill-down : 더 많은 정보를 찾기 위해 관련 텍스트나 아이콘 등을 클릭하여 마치 뚫고 들어가듯이 검색하는 것.

- 공통 태그는 모든 meter들에 적용되며, 다음 예제와 같이 설정될 수 있다.

management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod

※ Graphite 모니터링 시스템에서 공통 태그의 순서는 중요한데, 위와 같은 접근법(설정)으로는 공통 태그의 순서를 보장할 수 없기 때문에 custom MeterFilter을 정의하는 것을 권장한다.

 

(3) Per-meter(meter 단위) 속성

- MeterFilter bean들을 사용하는 방법 외에도, 속성을 이용하여 meter 단위로 커스터마이징 세트를 제한할 수 있다.

- Meter 단위 커스터마이징은 지정된 이름으로 시작하는 모든 meter ID들에 적용된다.

- 예를 들어, 다음 설정을 통해 example.remote으로 시작하는 모든 meter ID들을 비활성화할 수 있다.

management.metrics.enable.example.remote=false

- Meter 단위 커스터마이징 속성 목록

※ percentiles-histogram, percentiles, sla 개념 관련 문서 : https://micrometer.io/docs/concepts#_histograms_and_percentiles

 

 

7) Metrics Endpoint

- Spring Boot는 애플리케이션에 의해 수집된 metrics를 진단적으로 검사하는데 사용되는 metrics endpoint를 제공한다.

- Metrics endpoint는 기본적으로 비활성화되어 있기 때문에 노출 설정이 이루어져야 한다.

- /actuator/metrics에서는 사용 가능한 meter 이름들의 리스트를 볼 수 있다. 그리고, 선택자를 통해 이름을 제공함으로써 특정 meter에 관한 정보를 drill-down으로 확인할 수 있다.

※ 예) /actuator/metrics/jvm.memory.max

※ 여기에서 사용되는 이름은 모니터링 시스템으로 전달되는 명명 규칙이 정규화된 이후의 이름을 사용하면 안되고, 코드에서 사용되는 이름과 일치해야 한다. 예를 들어, Prometheus에서는 snake 명명 규칙에 의해 jvm.memory.max가 jvm_memory_max로 표시 되지만, metircs endpoint에서는 선택자로 jvm.memory.max를 사용해야 한다.

- URL에 tag=KEY:VALUE 형식의 query parameter들을 추가함으로써, meter에 대한 차원적인 drill-down을 제공할 수 있다.

예) /actuator/metrics/jvm.memory.max?tag=area:nonheap

※ 보고된 측정치들은 meter의 이름과 적용된 태그들에 매칭되는 모든 meter들에 대한 통계들을 합산한 것이다. 즉, 위의 예시에서 반환되는 "Value" 통계치는 heap의 "Code Cache", "Compressed Class Space", "Metaspace" 영역들의 최대 메모리 사용량의 합산값이 된다. 만약 "Metaspace"의 크기만을 보고 싶다면, tag=id:Metaspace query parameter를 추가하면 된다.

예) /actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace

 

 

 

5. Auditing

- Spring Security가 활성화되어 있으면, Spring Boot Actuator는 이벤트들을 표시해주는 검사 프레임워크를 제공한다.

※ 기본적인 이벤트로는 “authentication success”, “failure”, 그리고 “access denied” 예외가 있다.

- 이 기능은 보고(report)나 인증 실패 기반의 잠금 정책을 구현하는데에 유용하다.

- 표시된 보안 이벤트들을 커스터마이징 하기 위해서 AbstractAuthenticationAuditListener과 AbstractAuthorizationAuditListener의 구현체를 별도로 만들 수 있다.

- 검사 서비스를 자체 비즈니스 이벤트에도 적용할 수도 있다. 이를 위해서, 기존의 AuditEventRepository를 우리의 컴포넌트에 주입받아서 직접 사용하거나, ApplicationEventPublisherAware 인터페이스를 구현해서 ApplicationEventPublisher로 AuditApplicationEvent를 publish할 수도 있다.

 

 

 

6. HTTP Tracing

- 모든 HTTP 요청들에 대한 추적은 자동으로 활성화되어 있다. httptrace endpoint를 확인해서 최근 100개의 요청-응답 교환에 대한 기본적인 정보들을 얻을 수 있다.

 

HTTP 추적 커스터마이징하기

- 각 trace에 포함된 요소들을 커스터마이징하려면 management.trace.http.include 속성을 사용하면 된다. 더 많은 커스터마이징을 위해서는 HttpExchangeTracer 구현체를 직접 만들어서 등록하는 방법도 있다.

- 기본적으로, 최근 100개의 요청-응답 교환에 대한 trace들을 저장하는 InMemoryHttpTraceRepository가 사용된다. 저장 용량을 늘리기 위해서 직접 InMemoryHttpTraceRepository bean을 만들어서 등록할 수도 있고, HttpTraceRepository 구현체를 직접 만드는 방법도 있다.

 

 

 

7. Process Monitoring

- spring-boot 모듈에 프로세스 모니터링에 유용한 파일들을 생성하는 2개의 클래스가 있다.

  • ApplicationPidFileWriter 클래스 : application PID를 포함하는 파일을 생성한다. 기본적으로, application 디렉토리 안에 application.pid 파일로 존재한다.
  • WebServerPortFileWriter 클래스 : 실행중인 웹 서버의 포트들을 포함하는 파일 또는 파일들을 생성한다. 기본적으로, application 디렉토리 안에 application.port 파일로 존재한다.

- 이 writer들은 기본적으로 비활성화되어 있기 때문에 우리가 직접 활성화해야 한다. 먼저, META-INF/spring.factories 파일에서 PID 파일을 작성하는 리스너들을 활성화하는 방법이 있다.

org.springframework.context.ApplicationListener=\
org.springframework.boot.context.ApplicationPidFileWriter,\
org.springframework.boot.web.context.WebServerPortFileWriter

그리고, 프로그래밍적인 방법으로는 SpringApplication.addListeners(...) 메소드를 깨우고 적절한 Writer 객체를 넘겨줌으로써 리스너를 활성화 시키는 방법이 있다. 이 메소드를 통해 Writer 생성자에서 파일의 이름과 경로를 커스터마이징할 수도 있다.

 

 

 

8. Cloud Foundry Support

1) Cloud Foundry Support 소개

- Spring Boot의 actuator 모듈은 호환 가능한 Cloud Foundry 인스턴스에 배포할 때 활성화되는 추가적인 지원을 포함한다. /cloudfoundryapplication 경로에서는 모든 @Endpoint bean들에 대하여 보안이 적용된 대체 라우트를 제공한다.

- 이 확장 지원을 통해서, Cloud Foundry 관리 UI들(예 - 배포된 애플리케이션들을 볼 수 있도록 사용되는 웹 애플리케이션)이 Spring Boot actuator 정보로 보강되도록 할 수 있다. 예를 들어, 애플리케이션 상태 페이지는 일반적인 "running" 이나 "stopped" 상태 대신에 전체 health 정보를 포함할 수 있다.

※ /cloudfoundryapplication 경로에는 일반 사용자가 접근할 수 없는데, 이 endpoint를 이용하려면 유효한 UAA 토큰이 request와 함께 넘어와야 한다.

 

 

2) Cloud Foundry Support 비활성화 하기

management.cloudfoundry.enabled=false

 

 

3) Cloud Foundry 자체 서명 인증서

- 기본적으로, /cloudfoundryapplication endpoint에 대한 보안 인증으로 SSL이 다양한 Cloud Foundry 서비스에서 호출될 수 있다.

- 만약 우리의 Cloud Foundry UAA 또는 Cloud Controller 서비스가 자체 서명 인증서를 이용해야 한다면, 다음과 같은 설정이 필요하다.

management.cloudfoundry.skip-ssl-validation=true

 

 

4) Context path 커스터마이징하기

- 서버의 context-path가 /로 설정되어 있지 않다면, Cloud Foundry endpoint들은 애플리케이션의 root에서 활성화되지 않는다. server.servlet.context-path의 속성값이 /app이라면, Cloud Foundry endpoint들은 /app/cloudfoundryapplication/*에서 활성화된다.

- Cloud Foundry endpoint들이 서버의 context-path에 상관없이 항상 /cloudfoundryapplication/*에서 활성화되도록 하려면, 애플리케이션 안에서 명시적인 설정이 이루어져야 한다. 설정은 사용중인 웹 서버에 따라 달라지는데, Tomcat의 경우에는 다음과 같은 설정이 추가될 수 있다.

@Bean
public TomcatServletWebServerFactory servletWebServerFactory() {
	return new TomcatServletWebServerFactory() {

		@Override
		protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
			super.prepareContext(host, initializers);
			StandardContext child = new StandardContext();
			child.addLifecycleListener(new Tomcat.FixContextListener());
			child.setPath("/cloudfoundryapplication");
			ServletContainerInitializer initializer = getServletContextInitializer(getContextPath());
			child.addServletContainerInitializer(initializer, Collections.emptySet());
			child.setCrossContext(true);
			host.addChild(child);
		}

	};
}

private ServletContainerInitializer getServletContextInitializer(String contextPath) {
	return (c, context) -> {
		Servlet servlet = new GenericServlet() {

			@Override
			public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
				ServletContext context = req.getServletContext().getContext(contextPath);
				context.getRequestDispatcher("/cloudfoundryapplication").forward(req, res);
			}

		};
		context.addServlet("cloudfoundry", servlet).addMapping("/*");
	};
}

 

 

 

 

 

 

 

 

 

 

 

 

반응형

댓글