원문 - Production-ready Features


  1. 프로덕션 준비 기능(Production-ready Features)
    • 13.1. 프로덕션에 준비 기능 활성화(Enabling Production-ready Features)
    • 13.2. 엔드포인트(Endpoints)
      • 13.2.1. 엔드포인트 활성화(Enabling Endpoints)
      • 13.2.2. 엔드포인트 노출(Exposing Endpoints)
      • 13.2.3. 보안(Security)
        • 크로스 사이트 요청 위조 방지(Cross Site Request Forgery Protection)
      • 13.2.4. 엔드포인트 구성(Configuring Endpoints)
      • 13.2.5. 액추에이터 웹 엔드포인트를 위한 하이퍼미디어(Hypermedia for Actuator Web Endpoints)
      • 13.2.6. CORS 지원(CORS Support)
      • 13.2.7. 커스텀 엔드포인트 구현(Implementing Custom Endpoints)
        • 입력 받기(Receiving Input)
        • 커스텀 웹 엔드포인트(Custom Web Endpoints)
        • 서블릿 엔드포인트(Servlet Endpoints)
        • 컨트롤러 엔드포인트(Controller Endpoints)
      • 13.2.8. 상태 정보(Health Information)
        • 헬스인디케이터 자동 구성(Auto-configured HealthIndicators)
        • 커스텀 헬스인디케이터 작성. 리액티브 헬스인디케이터(Writing Custom HealthIndicators. Reactive Health Indicators)
        • 자동 구성된 리액티브헬스인디케이터 상태 그룹(Auto-configured ReactiveHealthIndicators Health Groups)
        • 데이터소스 상태(DataSource Health)
      • 13.2.9. 쿠버네티스 프로브(Kubernetes Probes)
        • 쿠버네티스 프로브로 외부 상태 확인(Checking External State With Kubernetes Probes)
        • 애플리케이션 생명주기 및 프로브 상태(Application Lifecycle and Probe States)
      • 13.2.10. 애플리케션 정보(Application Information)
        • 자동 구성된 인포컨트리뷰터(Auto-configured InfoContributors)
        • 커스텀 애플리케이이션 정보(Custom Application Information)
        • 깃 커밋 정보(Git Commit Information)
        • 빌드 정보(Build Information)
        • 자바 정보(Java Information)
        • OS 정보(OS Information)
        • 커스텀 인포컨트리뷰터 개발(Writing Custom InfoContributors)
      • 13.3. HTTP 모니터링과 관리(Monitoring and Management Over HTTP)
        • 13.3.1. 관리 엔드포인트 경로 커스텀(Customizing the Management Endpoint Paths)
        • 13.3.2. 관리 서버 포트 커스텀(Customizing the Management Server Port)
        • 13.3.3. 관리별 SSL 구성(Configuring Management-specific SSL)
        • 13.3.4. 관리 서버 주소 커스텀(Customizing the Management Server Address)
        • 13.3.5. HTTP 엔드포인트 비활성화(Disabling HTTP Endpoints)
      • 13.4. JMX를 통한 모니터링 및 관리(Monitoring and Management over JMX)
        • 13.4.1. Customizing MBean Names
        • 13.4.2. Disabling JMX Endpoints
      • 13.5. 옵저버블리티(Observability)
      • 13.6. 로거(Loggers)
        • 13.6.1. 로거 구성(Configure a Logger)
      • 13.7. 메트릭(Metrics)
        • 13.7.1. 시작하기(Getting started)
        • 13.7.2. 지원되는 모터링 시스템(Supported Monitoring Systems)
          • 앱옵틱스(AppOptics)
          • 아틀라스(Atlas)
          • 데이터독(Datadog)
          • 다이나트레이스(Dynatrace)
          • 엘라스틱(Elastic)
          • 강글리아(Ganglia)
          • 그라파이트(Graphite)
          • 휴미오(Humio)
          • 인플럭스(Influx)
          • JMX
          • 카이로스DB(KairosDB)
          • 뉴 레릭(New Relic)
          • 오픈텔레메트리(OpenTelemetry)
          • 프로메테우스(Prometheus)
          • 시그널Fx(SignalFx)
          • 심플(Simple)
          • 스택드라이버(Stackdriver)
          • 스태스디(StatsD)
          • 웨이브프론트(Wavefront)
        • 13.7.3. 메트릭 및 미터 지원(Supported Metrics and Meters)
          • JVM 메트릭(JVM Metrics)
          • 시스템 메트릭(System Metrics)
          • 애플리케이션 시작 메트릭(Application Startup Metrics)
          • 로거 메트릭(Logger Metrics)
          • 작업 실행 및 스케줄링 메트릭(Task Execution and Scheduling Metrics)
          • 스프링 MVC 메트릭(Spring MVC Metrics)
          • 스프링 웹플럭스 메트릭(Spring WebFlux Metrics)
          • 저지 서버 메트릭(Jersey Server Metrics)
          • HTTP 클라이언트 메트릭(HTTP Client Metrics)
          • 톰캣 메트릭(Tomcat Metrics)
          • 캐시 메트릭(Cache Metrics)
          • 스프링 배치 메트릭(Spring Batch Metrics)
          • 스프링 그래프QL 메트릭(Spring GraphQL Metrics)
          • 데이터소스 메트릭(DataSource Metrics)
          • 하이버네이트 메트릭(Hibernate Metrics)
          • 스프링 데이터 리포지터리 메트릭(Spring Data Repository Metrics)
          • 래빗MQ 메트릭(RabbitMQ Metrics)
          • 스프링 인테그레이션 메트릭(Spring Integration Metrics)
          • 카프카 메트릭(Kafka Metrics)
          • 몽고DB 메트릭(MongoDB Metrics)
          • 제티 메트릭(Jetty Metrics)
          • @Timed 어노테이션 지원(@Timed Annotation Support)
          • 레디스 메트릭(Redis Metrics)
        • 13.7.4. 커스텀 메트릭 등록(Registering Custom Metrics)
        • 13.7.5. 개별 메트릭 커스텀(Customizing Individual Metrics)
          • 공통 태그(Common Tags)
          • 미터별 프로퍼티(Per-meter Properties)
        • 13.7.6. 메트릭 엔드포인트(Metrics Endpoint)
        • 13.7.7. 마이크로미터 옵저베이션과의 통합(Integration with Micrometer Observation)
      • 13.8. 트레이싱(Tracing)
        • 13.8.1. 트레이서 지원(Supported Tracers)
        • 13.8.2. 시작하기(Getting Started)
        • 13.8.3. 트레이서 구현체(Tracer Implementations)
          • 집킨과 오픈텔레메트리(OpenTelemetry With Zipkin)
          • 웨이브프론트와 오픈텔레메트리(OpenTelemetry With Wavefront)
          • OTLP와 오픈텔레메트리(OpenTelemetry With OTLP)
          • 집킨과 오픈집킨 브레이브(OpenZipkin Brave With Zipkin)
          • 웨이브프론트와 오픈집킨 브레이브(OpenZipkin Brave With Wavefront)
        • 13.8.4. 마이크로미터 옵저베이션과 통합(Integration with Micrometer Observation)
        • 13.8.5. 커스텀 스팬 만들기(Creating Custom Spans)
      • 13.9. 오디팅(Auditing)
        • 13.9.1. 커스텀 오디팅(Custom Auditing)
      • 13.10. HTTP 교환 기록(Recording HTTP Exchanges)
        • 13.10.1. 커스텀 HTTP 교환 기록(Custom HTTP Exchange Recording)
      • 13.11. 프로레스 모니터링(Process Monitoring)
        • 13.11.1. 구성 확장(Extending Configuration)
        • 13.11.2. 프로그래밍 방식으로 프로세스 모니터링 구성 활성화(Programmatically Enabling Process Monitoring)
      • 13.12. 클라우드 파운드리 지원(Cloud Foundry Support)
        • 13.12.1. 확장 클라우드 파운드리 액추에이터 지원 비활성화
        • 13.12.2. 클라우드 파운드리 자체 서명 인증서(Cloud Foundry Self-signed Certificates)
        • 13.12.3. 커스텀 컨텍스트 패스(Custom Context Path)
      • 13.13. 다음에 읽을 내용(What to Read Next) ***

13. 프로덕션 준비 기능(Production-ready Features)

스프링 부트에는 애플리케이션을 프로덕션 환경으로 푸시할 때 애플리케이션을 모니터링하고 관리하는 데 도움이 되는 다양한 추가 기능이 포함되어 있다. HTTP 엔드포인트나 JMX를 사용하여 애플리케이션을 관리하고 모니터링하도록 선택할 수 있다. 감사(Auditing), 상태(health) 및 지표 수집(metrics gathering)도 애플리케이션에 자동으로 적용될 수 있다.

13.1. 프로덕션 준비 기능 활성화(Enabling Production-ready Features)

spring-boot-actuator 모듈은 스프링 부트의 프로덕션 준비 기능을 모두 제공한다. 기능을 활성화하는 권장 방법은 spring-boot-starter-actuator “스타터” 의존성을 추가하는 것이다.

액추에이터 정의

액추에이터(Actuator)는 무언가를 움직이거나 제어하기 위한 기계 장치를 가리키는 제조 용어다. 액추에이터는 작은 변화로 많은 양의 모션을 생성할 수 있다.

메이븐 기반 프로젝트에 액추에이터를 추가하려면 다음 “스타터” 의존성을 추가하자.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

그레이들의 경우 다음 선언을 사용한다.

dependencies {
      implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

13.2. 엔드포인트(Endpoints)

액추에이터 엔드포인트를 사용하면 애플리케이션을 모니터링하고 상호 작용할 수 있다. 스프링 부트에는 여러 내장 엔드포인트가 포함되어 있으며 사용자가 직접 엔드포인트를 추가할 수 있다. 예를 들어 상태(health) 엔트포인트는 기본 애플리케이션의 상태 정보를 제공한다.

각 개별 엔드포인트을 활성화하거나 비활성화하고 HTTP 또는 JMX를 통해 노출(원격 접근 가능)할 ​​수 있다. 엔드포인트는 활성화되고 노출되면 사용 가능한 것으로 간주된다. 기본 제공 엔드포인트는 사용 가능한 경우에만 자동 구성된다. 대부분의 애플리케이션은 엔드포인트 ID와 /actuator 접두사가 URL에 매핑되는 HTTP를 통한 노출을 선택한다. 예를 들어 기본적으로 상태 엔드포인트는 /actuator/health에 매핑된다.

액추에이터의 엔드포인트와 해당 요청 및 응답 형식에 대해 자세히 알아보려면 별도의 API 설명서(HTML 또는 PDF)를 참고하자.

다음과 같은 기술 독립적인 엔드포인트를 사용할 수 있다

ID설명
auditevents현재 애플리케이션에 대한 감시(audit) 이벤트 정보를 노출한다. 어디트이벤트리포지터리(AuditEventRepository) 빈이 필요하다.
beans애플리케이션에 있는 모든 스프링 빈 전체 목록을 표시한다.
caches사용 가능한 캐시를 노출한다.
conditions구성 및 자동 구성 클래스에서 평가된(evaluated) 조건과 일치하거나 일치하지 않는 이유를 표시한다.
configprops모든 @ConfigurationProperties의 대조 목록을 표시한다.
env스프링의 컨피규러블인바이런먼트(ConfigurableEnvironment)에서 프로퍼티를 노출한다.
flyway적용된 모든 Flyway 데이터베이스 마이그레이션을 표시한다. 하나 이상의 Flyway 빈이 필요하다.
health애플리케이션 상태 정보를 표시한다.
httpexchangesHTTP 교환 정보(기본적으로 마지막 100개의 HTTP 요청-응답 교환)를 표시한다. HttpExchangeRepository 빈이 필요하다.
info임의의 애플리케이션 정보를 표시합니다.
integrationgraph스프링 인테그레이션 그래프를 표시한다. spring-integration-core에 대한 의존성이 필요하다.
loggers애플리케이션의 로거 구성을 표시하고 수정한다.
liquibase적용된 모든 Liquibase 데이터베이스 마이그레이션을 표시한다. 하나 이상의 Liquibase 빈이 필요하다.
metrics현재 애플리케이션에 대한 “메트릭(metrics)” 정보를 표시한다.
mappings모든 @RequestMapping 경로의 조합된 목록을 표시한다.
quartz쿼츠 스케줄러 잡에 대한 정보를 표시한다.
scheduledtasks애플리케이션에 예약된 작업을 표시한다.
sessions스프링 세션 지원 세션 리포지터리에서 사용자 세션을 검색하고 삭제할 수 있다. 스프링 세션을 사용하는 서블릿 기반 웹 애플리케이션이 필요하다.
shutdown애플리케이션을 정상적으로 종료할 수 있다. jar 패키징을 사용할 때만 작동한다. 일반적으로 비활성화되어 있다.
startup어플리케이션스타드업(ApplicationStartup)에서 수집한 시작 단계 데이터를 표시한다. 버퍼링애플리케이션스타드업(BufferingApplicationStartup)으로 구성하려면 스프링애플리케이션(SpringApplication)이 필요하다.
threaddump스레드덤프를 수행한다.

애플리케이션이 웹 애플리케이션(스프링 MVC, 스프링 웹플러스 또는 Jersey)인 경우 다음과 같은 추가 엔드포인트를 사용할 수 있다.

ID설명
heapdump힙 덤프 파일을 반환한다. 핫스팟(HotSpot) JVM에서는 HPROF 타입의 파일이 반환된다. OpenJ9 JVM에서는 PHD 타입의 파일이 반환된다.
logfile로그 파일의 내용을 반환한다(logging.file.name 또는 login.file.path 프로퍼티가 설정된 경우). 로그 파일 콘텐츠의 일부를 검색하기 위해 HTTP Range 헤더 사용을 지원한다.
prometheus프로메테우스(Prometheus) 서버에서 스크랩할 수 있는 형식으로 측정항목을 노출한다. micrometer-registry-prometheus에 대한 의존성이 필요하다.

13.2.1. 엔드포인트 활성화(Enabling Endpoints)

기본적으로 종료(shutdown)를 제외한 모든 엔드포인트는 활성화되어있다. 엔드포인트 활성화하려면 해당 management.endpoint.<id>.enabled 프로퍼티를 사용하자. 다음 예제에서는 종료 엔드포인트를 활성화한다.

프로퍼티스(Properties)

management.endpoint.shutdown.enabled=true

Yaml

management:
  endpoint:
    shutdown:
      enabled: true

옵트아웃(opt-out)이 아닌 옵트인(opt-in)으로 엔드포인트 활성화를 선호하는 경우 management.endpoints.enabled-by-default 프로퍼티를 false로 설정하고 개별 엔드포인트 활성화 프로퍼티를 사용하여 다시 옵트인한다. 다음 예제에서는 info 엔드포인트를 활성화하고 다른 모든 엔드포인트를 비활성화한다.

프로퍼티스(Properties)

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true

Yaml

management:
    endpoints:
      enabled-by-default: false
    endpoint:
      info:
        enabled: true

비활성화된 엔드포인트는 애플리케이션 컨텍스트에서 완전히 제거된다. 엔드포인트가 노출되는 기술만 변경하려면 includeexclude 프로퍼티스를 사용하자.

13.2.2. 엔드포인트 노출(Exposing Endpoints)

기본적으로 상태 엔드포인트만 HTTP 및 JMX를 통해 노출된다. 엔드포인트에는 민감한 정보가 포함될 수 있으므로 이를 노출을 신중하게 고려해야 한다.

노출되는 엔드포인트를 변경하려면 다음 기술별 includeexclude 프로퍼티스를 사용하자.

프로퍼티기본값
management.endpoints.jmx.exposure.exclude 
management.endpoints.jmx.exposure.includehealth
management.endpoints.web.exposure.exclude 
management.endpoints.web.exposure.includehealth

include 프로퍼티는 노출된 엔드포인트의 ID를 나열한다. exclude 프로퍼티는 노출되어서는 안 되는 엔드포인트의 ID를 나열한다. exclude 프로퍼티는 include 프로퍼티보다 우선된다. 엔드포인트 ID 목록을 사용하여 include 프로퍼티 및 exclude 프로퍼티을 모두 구성할 수 있다.

예를 들어, JMX를 통해서만 상태(health) 및 정보(info) 엔드포인트를 노출하려면 다음 프로퍼티를 사용한다.

프로퍼티스(Properties)

management.endpoints.jmx.exposure.include=health,info

Yaml

management:
  endpoints:
    jmx:
      exposure:
        include: "health,info"

*를 사용하여 모든 엔드포인트를 선택할 수 있다. 예를 들어, envbeans 엔드포인트를 제외한 모든 것을 HTTP를 통해 노출하려면 다음 프로퍼티를 사용하자.

프로퍼티스(Properties)

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans

Yaml

management:
  endpoints:
    web:
      exposure:
        include: "*"
        exclude: "env,beans"

*는 YAML에서 특별한 의미를 가지므로 모든 엔드포인트를 포함(또는 제외)하려면 따옴표를 추가해야 한다.

애플리케이션이 공개적으로 노출되는 경우, 엔드포인트도 보호하는 것이 좋다.

엔드포인트가 노출에 대한 자체 전략을 구현하려면 EndpointFilter 빈을 등록할 수 있다.

13.2.3. 보안(Security)

보안을 위해 기본적으로 HTTP를 통해 /health 엔드포인트만 노출된다. management.endpoints.web.exposure.include 프로퍼티를 사용하여 노출되는 엔드포인트를 구성할 수 있다.

management.endpoints.web.exposure.include를 설정하기 전에 노출된 액추에이터에 민감한 정보가 포함되어 있지 않은지, 방화벽 뒤에 배치하여 보호되는지 또는 스프링 시큐리티와 같은 것으로 보호되는지 확인하자.

스프링 시큐리티가 클래스패스에 있고 다른 SecurityFilterChain 빈이 없는 경우 /health를 제외한 모든 액추에이터는 스프링 부트 자동 구성으로 보호된다. 커스텀 SecurityFilterChain 빈을 정의하면 스프링 부트 자동 구성이 중단되고 액추에이터 접근 규칙을 완전히 제어할 수 있다.

HTTP 엔드포인트에 대한 커스텀 보안을 구성하려는 경우(예: 특정 역할을 가진 사용자만 접근할 수 있도록 허용) 스프링 부트는 스프링 시큐리티와 함께 사용할 수 있는 몇 가지 편리한 RequestMatcher 객체를 제공한다.

일반적인 스프링 시큐리티 구성은 다음 예제와 유사할 수 있다.

자바

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(EndpointRequest.toAnyEndpoint());
        http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
        http.httpBasic(withDefaults());
        return http.build();
    }
}

코틀린

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.Customizer.withDefaults
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain

@Configuration(proxyBeanMethods = false)
class MySecurityConfiguration {
    @Bean
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests { requests ->
            requests.anyRequest().hasRole("ENDPOINT_ADMIN")
        }
        http.httpBasic(withDefaults())
        return http.build()
    }
}

이전 예제에서는 EndpointRequest.toAnyEndpoint()를 사용하여 요청을 모든 엔드포인트에 일치시킨 다음 모든 엔드포인트에 ENDPOINT_ADMIN 역할이 있는지 확인한다. EndpointRequest에서는 다른 여러 매처(matcher) 메서드도 사용할 수 있다. 자세한 내용은 API 설명서(HTML 또는 PDF)를 참고하자.

방화벽 뒤에 애플리케이션을 배포하는 경우 인증 없이 모든 액추에이터 엔드포인트에 접근할 수 있는 것을 선호할 수 있다. 다음과 같이 management.endpoints.web.exposure.include 프로퍼티를 변경하면 된다.

프로퍼티스(Properties)

management.endpoints.web.exposure.include=*

Yaml

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

또한, 스프링 시큐리티가 있는 경우 다음 예제와 같이 엔드포인트에 대한 인증되지 않은 접근를 허용하는 커스텀 보안 구성을 추가해야 한다.

자바

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {
  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.securityMatcher(EndpointRequest.toAnyEndpoint());
    http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
    return http.build();
  } 
}

코틀린

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain

@Configuration(proxyBeanMethods = false)
class MySecurityConfiguration {
  @Bean
  fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
    http.securityMatcher(EndpointRequest.toAnyEndpoint()).authorizeHttpRequests { requests ->
      requests.anyRequest().permitAll()
    }
    return http.build()
  }
}

위의 두 예제에서 구성은 액추에이터 엔드포인트에만 적용된다. 스프링 부트의 보안 구성은 SecurityFilterChain 빈이 있는 경우 완전히 백오프되므로 애플리케이션의 나머지 부분에 적용되는 규칙을 사용하여 추가 SecurityFilterChain 빈을 구성해야 한다.

크로스 사이트 요청 위조 방지(Cross Site Request Forgery Protection)

스프링 부트는 스프링 시큐리티의 기본값을 사용하므로 CSRF 보호는 기본적으로 켜져 있다. 이는 기본 보안 구성이 사용 중일 때 POST(종료 및 로거 엔드포인트), PUT 또는 DELETE가 필요한 액추에이터 엔드포인트에 403(금지됨) 오류가 발생함을 의미한다.

브라우저가 아닌 클라이언트에서 사용되는 서비스를 생성하는 경우에만 CSRF 보호를 완전히 비활성화하는 것이 좋다.

스프링 시큐리티 레퍼런스 가이드에서 CSRF 보호에 대한 추가 정보를 찾을 수 있다.

13.2.4. 엔드포인트 구성(Configuring Endpoints)

엔드포인트가 응답을 캐시하는 시간을 구성하려면 해당 cache.time-to-live 프로퍼티를 사용하자. 다음 예제에서는 빈 엔드포인트 캐시의 TTL(Time-To-Live)을 10초로 설정합니다.

프로퍼티스(Properties)

management.endpoint.beans.cache.time-to-live=10s

Yaml

management:
  endpoint:
    beans:
      cache:
        time-to-live: "10s"

management.endpoint.<name> 접두사는 구성 중인 엔드포인트를 고유하게 식별한다.

13.2.5. 액추에이터 웹 엔드포인트를 위한 하이퍼미디어(Hypermedia for Actuator Web Endpoints)

모든 엔드포인트에 대한 링크가 포함된 “discovery page”가 ​​추가된다. “discovery page”는 기본적으로 /actuator에서 사용할 수 있다.

“discovery page”를 비활성화하려면 애플리케이션 프로퍼티스에서 다음 프로퍼티를 추가해보자.

프로퍼티스(Properties)

management.endpoints.web.discovery.enabled=false

Yaml

management:
  endpoints:
    web:
      discovery:
        enabled: false

커스텀 관리 컨텍스트 패스가 구성되면 “discovery page”가 ​​자동으로 /actuator에서 관리 컨텍스트의 루트로 이동한다. 예를 들어 관리 컨텍스트 패스가 /management인 경우 /management에서 “discovery page”를 사용할 수 있다. 관리 컨텍스트 패스가 /로 설정되면 다른 매핑과의 충돌 가능성을 방지하기 위해 discovery page가 비활성화된다.

13.2.6. CORS 지원(CORS Support)

CORS(Cross-Origin Resource Sharing)는 도메인 간 요청에 대한 승인을 유연하게 지정할 수 있는 W3C 사양이다. 스프링 MVC 또는 스프링 웹플럭스를 사용하는 경우 이런 상황을 지원하도록 액추에이터의 웹 엔드포인트를 구성할 수 있다.

CORS 지원은 기본적으로 비활성화되어 있으며 management.endpoints.web.cors.allowed-origins 프로퍼티를 설정한 후에만 활성화된다. 다음 구성은 example.com 도메인에서 GET 및 POST 호출을 허용한다.

프로퍼티스(Properties)

management.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST

Yaml

management:
  endpoints:
    web: 
      cors:
        allowed-origins: "https://example.com"
        allowed-methods: "GET,POST"

전체 옵션 목록은 CorsEndpointProperties를 참고하자.

13.2.7. 커스텀 엔드포인트 구현(Implementing Custom Endpoints)

@Endpoint 어노테이션이 달린 @Bean을 추가하면 @ReadOperation, @WriteOperation 또는 @DeleteOperation으로 어노테이션이 달린 모든 메서드는 자동으로 JMX를 통해 노출되고 웹 애플리케이션에서는 HTTP를 통해서도 노출된다. Jersey, 스프링 MVC 또는 스프링 웹플럭스를 사용하여 HTTP를 통해 엔드포인트를 노출할 수 있다. Jersey와 스프링 MVC를 모두 사용할 수 있는 경우 스프링 MVC가 사용된다.

다음 예제에서는 커스텀 객체를 반환하는 리드 오퍼레이션(read operation)을 노출한다.

자바

@ReadOperation
public CustomData getData() {
    return new CustomData("test", 5);
}

코틀린

@ReadOperation
fun getData(): CustomData {
    return CustomData("test", 5)
}

@JmxEndpoint 또는 @WebEndpoint를 사용하여 기술별 엔드포인트를 작성할 수도 있다. 이러한 엔드포인트는 해당 기술로 제한된다. 예를 들어 @WebEndpoint는 JMX가 아닌 HTTP를 통해서만 노출된다.

@EndpointWebExtension@EndpointJmxExtension을 사용하여 기술별 확장을 작성할 수 있다. 이러한 어노테이션을 사용하면 기존 엔드포인트를 보강하는 기술별 작업을 제공할 수 있다.

마지막으로, 웹 프레임워크 특정 기능에 접근해야 하는 경우 JMX를 통해 또는 다른 웹 프레임워크를 사용할 때 사용할 수 없는 서블릿이나 스프링 @Controller@RestController 엔드포인트를 구현할 수 있다.

입력 받기(Receiving Input)

엔드포인트의 작업은 해당 파라미터를 통해 입력을 받는다. 웹을 통해 노출되면 이러한 파라미터의 값은 URL의 쿼리 파라미터와 JSON 요청 본문에서 가져온다. JMX를 통해 노출되면 파라미터는 MBean 작업의 파라미터에 매핑된다. 파라미터는 기본적으로 필수다. @javax.annotation.Nullable 또는 @org.springframework.lang.Nullable로 어노테이션을 달아 선택사항으로 만들 수 있다.

JSON 요청 본문(body)의 각 루트 프로퍼티를 엔드포인트의 파라미터에 매핑할 수 있다. 다음 JSON 요청 본문을 보자.

{
    "name": "test",
    "counter": 42
}

다음 예제와 같이 이를 사용하여 문자열명 및 int 카운터 파라미터를 사용하는 라이트 오퍼레이션(write operation)을 호출할 수 있다.

자바

@WriteOperation
public void updateData(String name, int counter) {
    // "test"와 42 주입
}

코틀린

@WriteOperation
fun updateData(name: String?, counter: Int) {
    // "test"와 42 주입
}

엔드포인트는 기술에 구애받지 않으므로 메서드 시그니처에는 단순 타입만 지정할 수 있다. 특히 CustomData 타입으로 단일 파라미터를 선언하는 경우 이름 및 카운터 프로퍼티스를 정의하는 것은 지원되지 않는다.

입력이 작업 메서드의 파라미터에 매핑되도록 하려면 엔드포인트를 구현하는 자바 코드는 -parameters로 컴파일해야 하고, 엔드포인트를 구현하는 코틀린 코드는 -java-parameters로 컴파일해야 한다. 이는 스프링 부트의 그레이들 플러그인을 사용하거나 메이븐 및 spring-boot-starter-parent를 사용하는 경우 자동으로 발생한다.

입력 유형 변환

엔드포인트 작업 메서드에 전달된 파라미터는 필요한 경우 필요한 타입으로 자동 변환된다. 작업 메서드를 호출하기 전에 JMX 또는 HTTP를 통해 수신된 입력은 @EndpointConverter로 정규화된 모든 컨버터(Converter) 또는 제네릭컨버터(GenericConverter) 빈뿐만 아니라 ApplicationConversionService 인스턴스를 사용하여 필요한 타입으로 변환된다.

커스텀 웹 엔드포인트

@Endpoint, @WebEndpoint 또는 @EndpointWebExtension에 대한 작업은 Jersey, 스프링 MVC 또는 스프링 웹플럭스를 사용하여 HTTP를 통해 자동으로 노출된다. Jersey와 스프링 MVC를 모두 사용할 수 있는 경우 스피링 MVC가 사용된다.

웹 엔드포인트 요청 조건자

웹에 노출된 엔드포인트의 각 작업에 대해 요청 조건자(predicate)가 자동으로 생성된다.

경로

조건자의 경로는 엔드포인트의 ID와 웹에 노출된 엔드포인트의 기본 경로에 의해 결정된다. 기본 기본 경로는 /actuator다. 예를 들어 세션 ID가 있는 엔드포인트는 /actuator/sessions를 조건자의 경로로 사용한다.

@Selector를 사용하여 작업 메서드의 하나 이상의 파라미터에 어노테이션을 추가하여 경로를 추가로 커스텀할 수 있다. 이러한 파라미터는 경로 변수로 경로 조건자에 추가된다. 엔드포인트 작업이 호출되면 변수 값이 작업 메서드에 전달된다. 나머지 모든 경로 요소를 캡처하려면 마지막 파라미터에 @Selector(Match=ALL_REMAINING)를 추가하고 이를 String[]과 변환 ​​가능한 타입으로 만들 수 있다.

HTTP 메소드

조건자의 HTTP 메서드는 다음 표에 표시된 대로 작업 유형에 따라 결정된다.

작업HTTP 메소드
@ReadOperationGET
@WriteOperationPOST
@DeleteOperationDELETE
소비

요청의 본문을 사용하는 @WriteOperation(HTTP POST)의 경우, 조건자의 소비 절은 application/vnd.spring-boot.actuator.v2+json, application/json다. 다른 모든 작업의 ​​경우 consumes 절은 비어 있다.

생산

조건자의 생산 절은 @DeleteOperation, @ReadOperation@WriteOperation 어노테이션의 생산 애트리뷰트에 의해 결정될 수 있다. 애트리뷰트는 선택사항이다. 사용되지 않으면 생산 절이 자동으로 결정된다.

작업 메서드가 void 또는 Void를 반환하는 경우 생성 절은 비어 있다. 작업 메서드가 org.springframework.core.io.Resource를 반환하는 경우 생성 절은 application/octet-stream이다. 다른 모든 작업의 ​​경우 생산 절은 application/vnd.spring-boot.actuator.v2+json, application/json이다.

웹 엔드포인트 응답 상태

엔드포인트 작업의 기본 응답 상태는 작업 타입(읽기, 쓰기 또는 삭제)과 작업이 반환하는 항목(있는 경우)에 따라 달라진다.

@ReadOperation이 값을 반환하는 경우 응답 상태는 200(정상)이 된다. 값을 반환하지 않는 경우 응답 상태는 404(찾을 수 없음)이다.

@WriteOperation 또는 @DeleteOperation이 값을 반환하는 경우 응답 상태는 200(정상)이 된다. 값을 반환하지 않는 경우 응답 상태는 204(콘텐츠 없음)이다.

필수 파라미터 없이 또는 필수 타입으로 변환할 수 없는 파라미터를 사용하여 작업을 호출하면 작업 메서드가 호출되지 않고 응답 상태가 400(Bad Request)이 된다.

웹 엔드포인트 범위 요청

HTTP 범위 요청을 사용하여 HTTP 리소스의 일부를 요청할 수 있다. 스프링 MVC 또는 스프링 웹플럭스를 사용할 때 org.springframework.core.io.Resource를 반환하는 작업은 자동으로 범위 요청을 지원한다.

Jersey를 사용하는 경우 범위 요청이 지원되지 않는다.

웹 엔드포인트 보안

웹 엔드포인트 또는 웹 특정 엔드포인트 확장에 대한 작업은 현재 java.security.Principal 또는 org.springframework.boot.actuate.endpoint.SecurityContext를 메서드 파라미터로 받을 수 있다. 전자는 일반적으로 @Nullable과 함께 사용되어 인증된 사용자와 인증되지 않은 사용자에게 서로 다른 동작을 제공한다. 후자는 일반적으로 isUserInRole(String) 메소드를 사용하여 권한 부여 확인을 수행하는 데 사용된다.

서블릿 엔드포인트(Servlet Endpoints)

@ServletEndpoint 어노테이션이 달린 클래스를 구현하고 @ServletEndpoint도 구현하는 클래스를 구현하여 서블릿을 엔드포인트로 노출할 수 있다. 서블릿 엔드포인트는 서블릿 컨테이너와의 더 깊은 통합을 제공하지만 이식성은 좋지않다. 이는 기존 서블릿을 엔드포인트로 노출하는 데 사용된다. 새 엔드포인트의 경우 @Endpoint@WebEndpoint 어노테이션을 선호한다.

컨트롤러 엔드포인트(Controller Endpoints)

@ControllerEndpoint@RestControllerEndpoint를 사용하여 스프링 MVC 또는 스프링 웹플럭스에 의해서만 노출되는 엔드포인트를 구현할 수 있다. 메서드는 @RequestMapping@GetMapping과 같은 스프링 MVC 및 스프링 웹플럭스용 표준 어노테이션을 사용하여 매핑되며 엔드포인트의 ID는 경로의 접두사로 사용된다. 컨트롤러 엔드포인트는 스프링의 웹 프레임워크와의 더 깊은 통합을 제공하지만 이식성은 좋지않다. 가능하면 @Endpoint@WebEndpoint 어노테이션을 선호해야 한다.

13.2.8. 상태 정보(Health Information)

상태 정보를 사용하여 실행 중인 애플리케이션의 상태를 확인할 수 있다. 이는 프로덕션 시스템이 다운될 때 누군가에게 경고하기 위해 모니터링 소프트웨어에서 자주 사용된다. 상태 엔드포인트에 의해 노출되는 정보는 다음 값 중 하나로 구성될 수 있는 management.endpoint.health.show-detailsmanagement.endpoint.health.show-comComponents 프로퍼티스에 따라 달라진다.

명칭설명
never세부정보 표시되지 않음.
when-authorized세부정보는 승인된 사용자에게만 표시된다. 승인된 역할은 management.endpoint.health.roles를 사용하여 구성할 수 있다.
always세부정보는 모든 사용자에게 표시된다.

기본값은 never다. 사용자가 하나 이상의 엔드포인트 역할에 속해 있으면 권한이 부여된 것으로 간주된다. 엔드포인트에 구성된 역할(기본값)이 없으면 인증된 모든 사용자는 권한이 부여된 것으로 간주한다. management.endpoint.health.roles 프로퍼티를 사용하여 역할을 구성할 수 있다.

애플리케이션을 보호하고 항상 사용하려면 보안 구성에서 인증된 사용자와 인증되지 않은 사용자 모두에 대해 상태 엔드포인트에 대한 접근를 허용해야 한다.

상태 정보는 HealthContributorRegistry(기본적으로 ApplicationContext에 정의된 모든 HealthContributor 인스턴스)의 콘텐츠에서 수집된다. 스프링 부트에는 자동으로 구성된 여러 HealthContributors가 포함되어 있으며 직접 작성할 수도 있다.

HealthContributorHealthIndicator 또는 CompositeHealthContributor일 수 있다. HealthIndicator는 상태를 포함한 실제 상태 정보를 제공한다. CompositeHealthContributor는 다른 HealthContributors을 제공한다. 컨트리뷰터는 종합적으로 트리 구조를 형성하여 전체 시스템 상태를 나타낸다.

기본적으로, 최종 시스템 상태는 순서가 지정된 상태 목록을 기반으로 각 HealthIndicator의 상태를 정렬하는 StatusAggregator에 의해 파생된다. 정렬된 목록의 첫 번째 상태는 전체 상태로 사용된다. HealthIndicatorStatusAggregator에 알려진 상태를 반환하지 않으면 UNKNOWN 상태가 사용된다.

HealthContributorRegistry를 사용하여 런타임 시 Health indicators를 등록 및 등록 취소할 수 있다.

헬스인디케이터 자동 구성(Auto-configured HealthIndicators)

적절한 경우, 스프링부트는 다음 표에 나열된 HealthIndicator를 자동 구성한다. 다음 표에 나열된 키를 사용하여 management.health.key.enabled를 구성하여 선택한 indicators를 활성화하거나 비활성화할 수도 있다.

명칭설명
cassandraCassandraDriverHealthIndicator카산드라 데이터베이스가 작동 중인지 확인한다.
couchbaseCouchbaseHealthIndicator카우치베이스 클러스터가 작동 중인지 확인한다.
dbDataSourceHealthIndicator데이터소스에 대한 연결을 얻을 수 있는지 확인한다.
diskspaceDiskSpaceHealthIndicator디스크 공간이 부족한지 확인한다.
elasticsearchElasticsearchRestHealthIndicator엘라스틱서치 클러스터가 작동 중인지 확인한다.
hazelcastHazelcastHealthIndicatorHazelcast 서버가 작동 중인지 확인한다.
influxdbInfluxDbHealthIndicatorInfluxDB 서버가 작동 중인지 확인한다.
jmsJmsHealthIndicatorJMS 브로커가 작동 중인지 확인한다.
ldapLdapHealthIndicatorLDAP 서버가 작동 중인지 확인한다.
mailMailHealthIndicator메일 서버가 작동 중인지 확인한다.
mongoMongoHealthIndicator몽고 데이터베이스가 작동 중인지 확인한다.
neo4jNeo4jHealthIndicatorNeo4j 데이터베이스가 작동 중인지 확인한다.
pingPingHealthIndicator항상 UP으로 응답한다.
rabbitRabbitHealthIndicatorRabbit 서버가 작동 중인지 확인한다.
redisRedisHealthIndicator레디스 서버가 작동 중인지 확인한다.

management.health.defaults.enabled 프로퍼티를 설정하여 이를 모두 비활성화할 수 있다.

추가 HealthIndicators를 사용할 수 있지만 기본적으로 활성화되어 있지 않다.

명칭설명
livenessstateLivenessStateHealthIndicator“Liveness” 애플리케이션 가용성 상태를 노출한다.
readinessstateReadinessStateHealthIndicator“Readiness” 애플리케이션 가용성 상태를 노출한다.

커스텀 헬스인디케이터 작성. 리액티브 헬스인디케이터(Writing Custom HealthIndicators. Reactive Health Indicators)

커스텀 상태 정보를 제공하기 위해 HealthIndicator 인터페이스를 구현하는 스프링 빈을 등록할 수 있다. health() 메서드 구현을 제공하고 Health 응답을 반환해야 한다. 상태 응답에는 상태가 포함되어야 하며 선택적으로 표시할 추가 세부 정보를 포함할 수 있다. 다음 코드는 샘플 HealthIndicator 구현을 보여준다.

자바

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class MyHealthIndicator implements HealthIndicator {
  @Override
  public Health health() {
      int errorCode = check();
      if (errorCode != 0) {
          return Health.down().withDetail("Error Code", errorCode).build();
      }
      return Health.up().build();
  }
  private int check() {
      // 특정 상태 점검을 수행한다.
      return ...
  } 
}

코틀린

import org.springframework.boot.actuate.health.Health
import org.springframework.boot.actuate.health.HealthIndicator
import org.springframework.stereotype.Component

@Component
class MyHealthIndicator : HealthIndicator {
  override fun health(): Health {
      val errorCode = check()
      if (errorCode != 0) {
          return Health.down().withDetail("Error Code", errorCode).build()
      }
      return Health.up().build()
  }
  private fun check(): Int {
      // 특정 상태 점검을 수행한다.
      return  ...
  } 
}

주어진 HealthIndicator의 식별자는 HealthIndicator 접미사가 없는 빈의 이름이다(존재하는 경우). 앞의 예에서 상태 정보는 my라는 항목에서 사용할 수 있다.

상태 표시기(Health indicator)는 일반적으로 HTTP를 통해 호출되며 연결 시간이 초과되기 전에 응답해야 한다. 스프링 부트는 응답하는 데 10초 이상 걸리는 상태 표시기에 대한 경고 메시지를 기록한다. 이 임계값을 구성하려면 management.endpoint.health.logging.slow-indicator-threshold 프로퍼티를 사용할 수 있다.

스프링 부트의 사전 정의된 상태 타입 외에도 Health는 새로운 시스템 상태를 나타내는 커스텀 상태를 반환할 수 있다. 이러한 경우 StatusAggregator 인터페이스의 커스텀 구현도 제공해야 한다. 또는 management.endpoint.health.status.order 구성 프로퍼티를 사용하여 기본 구현을 구성해야 한다.

예를 들어, HealthIndicator 구현 중 하나에서 FATAL 코드가 포함된 새 상태가 사용되고 있다고 가정하자. 심각도 순서를 구성하려면 애플리케이션 프로퍼티에 다음 프로퍼티스를 추가하자.

프로퍼티스(Properties)

management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up

Yaml

management:
  endpoint:
    health:
      status:
        order: "fatal,down,out-of-service,unknown,up"

응답의 HTTP 상태 코드는 전반적인 상태를 나타낸다. 기본적으로 OUT_OF_SERVICEDOWN503에 매핑된다. UP을 포함하여 매핑되지 않은 모든 상태는 200에 매핑된다. HTTP를 통해 상태 엔드포인트에 접근하는 경우 커스텀 상태 매핑을 등록할 수도 있다. 커스텀 매핑을 구성하면 DOWNOUT_OF_SERVICE에 대한 기본 매핑이 비활성화된다. 기본 매핑을 유지하려면 사용자 지정 매핑과 함께 이를 명시적으로 구성해야 한다. 예를 들어, 다음 프로퍼티는 FATAL을 503(서비스 사용 불가)에 매핑하고 DOWNOUT_OF_SERVICE에 대한 기본 매핑을 유지한다.

프로퍼티스(Properties)

management.endpoint.health.status.http-mapping.down=503
management.endpoint.health.status.http-mapping.fatal=503
management.endpoint.health.status.http-mapping.out-of-service=503

Yaml

management:
  endpoint:
    health:
      status:
        http-mapping:
          down: 503
          fatal: 503
          out-of-service: 503

더 많은 제어가 필요한 경우, 자체 HttpCodeStatusMapper 빈을 정의할 수 있다.

다음 표는 기본 제공 상태에 대한 기본 상태 매핑을 보여준다.

상태매핑
DOWNSERVICE_UNAVAILABLE (503)
OUT_OF_SERVICESERVICE_UNAVAILABLE (503)
UPNo mapping by default, so HTTP status is 200
UNKNOWNNo mapping by default, so HTTP status is 200

자동 구성된 리액티브헬스인디케이터 상태 그룹(Auto-configured ReactiveHealthIndicators Health Groups)

적절한 경우 스프링 부트는 다음 리액티브헬스인디케이터(ReactiveHealthIndicator)를 자동 구성한다.

명칭설명
cassandraCassandraDriverReactiveHealthIndicator카산드라 데이터베이스가 작동 중인지 확인한다.
couchbaseCouchbaseReactiveHealthIndicator카우치베이스 클러스터가 작동 중인지 확인한다.
elasticsearchElasticsearchReactiveHealthIndicator엘라스틱서치 클러스터가 작동 중인지 확인한다.
mongoMongoReactiveHealthIndicator몽고 데이터베이스가 작동 중인지 확인한다.
neo4jNeo4jReactiveHealthIndicatorNeo4j 데이터베이스가 작동 중인지 확인한다.
redisRedisReactiveHealthIndicator레디스 서버가 작동 중인지 확인한다.

필요한 경우 리액티브 표시기(indicator)가 일반 표시기를 대체한다. 또한 명시적으로 처리되지 않은 헬스인디케이터(HealthIndicator)는 자동으로 래핑된다.

상태 그룹(Health Groups)

상태 표시기를 다양한 목적으로 사용할 수 있는 그룹으로 구성하는 것이 유용한 경우가 있다.

상태 표시기 그룹을 추가하려면 management.endpoint.health.group.<name> 특성을 사용하고, 포함하거나 제외할 상태 표시기 ID 목록을 지정할 수 있다. 예를 들어, 데이터베이스 상태 표시기만 포함하는 그룹을 생성하려면 다음을 정의할 수 있다.

프로퍼티스(Properties)

management.endpoint.health.group.custom.include=db

Yaml

management:
  endpoint:
    health:
      group:
        custom:
          include: "db"

그런 다음 localhost:8080/actuator/health/custom을 눌러 결과를 확인할 수 있다.

마찬가지로, 그룹에서 데이터베이스 상태 표시기를 제외하고, 다른 모든 표시기를 포함하는 그룹을 생성하려면 다음을 정의할 수 있다.

프로퍼티스(Properties)

management.endpoint.health.group.custom.exclude=db

Yaml

management:
  endpoint:
    health:
      group:
        custom:
          exclude: "db"

기본적으로 상태 그룹에 존재하지 않는 상태 표시기가 포함되거나 제외되면 시작이 실패한다. 이 동작을 비활성화하려면 management.endpoint.health.validate-group-membershipfalse로 설정하자.

기본적으로, 그룹은 시스템 상태와 동일한 StatusAggregatorHttpCodeStatusMapper 설정을 상속한다. 그러나 그룹별로 이를 정의할 수도 있다. 필요한 경우 show-detailsroles 프로퍼티스을 오버라이드할 수도 있다.

프로퍼티스(Properties)

management.endpoint.health.group.custom.show-details=when-authorized
management.endpoint.health.group.custom.roles=admin
management.endpoint.health.group.custom.status.order=fatal,up
management.endpoint.health.group.custom.status.http-mapping.fatal=500
management.endpoint.health.group.custom.status.http-mapping.out-of-service=500

Yaml

management:
  endpoint:
    health:
      group:
        custom:
          show-details: "when-authorized"
          roles: "admin"
          status:
            order: "fatal,up"
            http-mapping:
              fatal: 500
              out-of-service: 500

그룹과 함께 사용할 커스텀 StatusAggregator 또는 HttpCodeStatusMapper 빈을 등록해야 하는 경우 @Qualifier("groupname")를 사용할 수 있다.

상태 그룹은 CompositeHealthContributor를 포함/제외할 수도 있다. CompositeHealthContributor의 특정 컴포넌트만 포함/제외할 수도 있다. 이는 다음과 같이 컴포넌트의 정규화된 이름을 사용하여 수행할 수 있다.

management.endpoint.health.group.custom.include="test/primary"
management.endpoint.health.group.custom.exclude="test/primary/b"

위의 예제에서 커스텀 그룹에는 복합 테스트의 컴포넌트인 primary라는 이름의 HealthContributor가 포함된다. 여기서 기본 자체는 복합이며 이름이 primary인 HealthContributor는 커스텀 그룹에서 제외된다.

상태 그룹은 기본 포트나 관리 포트의 추가 경로에서 사용할 수 있다. 이는 보안 목적으로 액추에이터 엔드포인트에 별도의 관리 포트를 사용하는 것이 일반적으로 쿠버네티스와 같은 클라우드 환경에서 유용하다. 별도의 포트를 사용하면 상태 확인에 성공하더라도 기본 애플리케이션이 제대로 작동하지 않을 수 있으므로 상태 확인을 신뢰할 수 없게 될 수 있다. 상태 그룹은 다음과 같은 추가 경로로 구성할 수 있다.

management.endpoint.health.group.live.additional-path="server:/healthz"

이렇게 하면 /healthz의 기본 서버 포트에서 라이브 상태 그룹을 사용할 수 있다. 접두사는 필수이며 server:(기본 서버 포트를 나타냄) 또는 management:(구성된 경우 관리 포트를 나타냄)이어야 한다. 경로는 단일 경로 세그먼트여야 한다.

데이터소스 상태(DataSource Health)

데이터소스(DataSource) 상태 표시기는 표준 데이터 소스와 라우팅 데이터 소스 빈 모두의 상태를 표시한다. 라우팅 데이터 소스의 상태는 각 대상 데이터 소스의 상태가 포함된다. 상태 엔드포인트의 응답에서 각 라우팅 데이터 원본의 대상은 해당 라우팅 키를 사용하여 이름이 지정된다. 표시기 출력에 라우팅 데이터 소스를 포함하지 않으려면 management.health.db.ignore-routing-data-sourcestrue로 설정하자.

13.2.9. 쿠버네티스 프로브(Kubernetes Probes)

쿠버네티스에 배포된 애플리케이션은 컨테이너 프로브를 통해 내부 상태에 대한 정보를 제공할 수 있다. 쿠버네티스 구성에 따라 kubelet은 해당 프로브를 호출하고 결과에 반응한다.

기본적으로, 스프링 부트는 애플리케이션 가용성 상태를 관리한다. 쿠버네티스 환경에 배포된 경우 액추에이터는 애플리케이션어베일러빌러티(ApplicationAvailability) 인터페이스에서 “활성” 및 “준비” 정보를 수집하고 전용 상태 표시기인 LivenessStateHealthIndicatorReadinessStateHealthIndicator에서 해당 정보를 사용한다. 이러한 표시기는 전역 상태 엔드포인트(“/actuator/health”)에 표시된다. 또한 상태 그룹 “/actuator/health/liveness” 및 “/actuator/health/readiness”를 사용하여 별도의 HTTP 프로브로 노출된다.

그런 다음 다음 엔드포인트 정보를 사용하여 쿠버네티스 인프라를 구성할 수 있다.

livenessProbe:
  httpGet:
    path: "/actuator/health/liveness"
    port: <actuator-port>
  failureThreshold: ...
  periodSeconds: ...
readinessProbe:
  httpGet:
    path: "/actuator/health/readiness"
    port: <actuator-port>
  failureThreshold: ...
  periodSeconds: ...

<actuator-port>는 액추에이터 엔드포인트를 사용할 수 있는 포트로 설정되어야 한다. 기본 웹 서버 포트일 수도 있고 “management.server.port” 프로퍼티가 설정된 경우 별도의 관리 포트일 수도 있다.

이러한 상태 그룹은 애플리케이션이 쿠버네티스 환경에서 실행되는 경우에만 자동으로 활성화된다. management.endpoint.health.probes.enabled 구성 프로퍼티를 사용하여 모든 환경에서 이를 활성화할 수 있다.

애플리케이션이 구성된 활성 기간보다 시작하는 데 시간이 더 오래 걸리는 경우 쿠버네티스는 솔루션으로 “startupProbe”를 언급한다. 일반적으로 모든 시작 작업이 완료될 때까지 “readinessProbe”가 실패하므로 여기서는 “startupProbe”가 반드시 필요하지는 않다. 이는 애플리케이션이 준비될 때까지 트래픽을 수신하지 않는다는 의미다. 그러나 애플리케이션을 시작하는 데 오랜 시간이 걸리는 경우 “startupProbe”를 사용하여 쿠버네티스가 시작하는 동안 애플리케이션을 종료하지 않도록 하는 것이 좋다. 애플리케이션 생명주기 동안 프로브가 작동하는 방식을 설명하는 장을 참고하자.

액추에이터 엔드포인트가 별도의 관리 컨텍스트에 배포된 경우 엔드포인트는 기본 애플리케이션과 동일한 웹 인프라(포트, 연결 풀, 프레임워크 컴포넌트)를 사용하지 않는다. 이 경우 기본 애플리케이션이 제대로 작동하지 않더라도(예: 새 연결을 수락할 수 없음) 프로브 검사에 성공할 수 있다. 이러한 이유로 활성 상태 및 준비 상태 그룹을 기본 서버 포트에서 사용할 수 있도록 만드는 것이 좋다. 이는 다음 프로퍼티를 설정하여 수행할 수 있다.

management.endpoint.health.probes.add-additional-paths=true

이렇게 하면 기본 서버 포트의 /livez에서 활성 상태를 사용할 수 있고 readyz를 준비 상태로 만들 수 있다.

쿠버네티스 프로브로 외부 상태 확인(Checking External State With Kubernetes Probes)

액추에이터는 “활성” 및 “준비” 프로브를 상태 그룹으로 구성한다. 이는 모든 상태 그룹 기능을 사용할 수 있음을 의미한다. 예를 들어 추가 상태 표시기를 구성할 수 있습니다.

프로퍼티스(Properties)

management.endpoint.health.group.readiness.include=readinessState,customCheck

Yaml

management:
  endpoint:
    health:
      group:
        readiness:
          include: "readinessState,customCheck"

기본적으로, 스프링 부트는 이러한 그룹에 다른 상태 표시기를 추가하지 않는다.

“활성” 프로브는 외부 시스템 상태 확인에 의존해서는 안 된다. 애플리케이션의 활성 상태가 손상된 경우 쿠버네티스는 애플리케이션 인스턴스를 재시작하여 해당 문제를 해결하려고 한다. 이는 외부 시스템(예: 데이터베이스, 웹 API 또는 외부 캐시)에 오류가 발생하면 쿠버네티스가 모든 애플리케이션 인스턴스를 재시작하고 연속적으로 실패할 수 있음을 의미한다.

“준비 상태” 프로브의 경우 애플리케이션 개발자는 외부 시스템 검사를 신중하게 선택해야 한다. 이러한 이유로 스프링 부트는 준비 상태 프로브에 추가 상태 확인을 포함하지 않는다. 애플리케이션 인스턴스의 준비 상태가 준비되지 않은 경우 쿠버네티스는 해당 인스턴스로 트래픽을 라우팅하지 않는다. 일부 외부 시스템은 애플리케이션 인스턴스에서 공유되지 않을 수 있으며, 이 경우 준비 상태 프로브에 포함될 수 있다. 다른 외부 시스템은 애플리케이션에 필수적이지 않을 수 있으며(애플리케이션에 서킷 브레이커(circuit breakers) 및 폴백이 있을 수 있음), 이 경우에는 반드시 포함되어서는 안 된다. 불행하게도 모든 애플리케이션 인스턴스가 공유하는 외부 시스템은 공통적이므로 판단을 내려야 한다. 이를 준비 상태 프로브에 포함하고 외부 서비스가 다운되면 애플리케이션이 서비스에서 제외될 것으로 예상한다. 호출자에서 서킷 브레이커를 사용하여 스택 위쪽의 오류를 처리한다.

애플리케이션의 모든 인스턴스가 준비되지 않은 경우 type=ClusterIP 또는 NodePort인 쿠버네티스 서비스는 들어오는 연결을 허용하지 않는다. 연결이 없기 때문에 HTTP 오류 응답(503 등)이 없다. type=LoadBalancer인 서비스는 공급자에 따라 연결을 허용할 수도 있고 허용하지 않을 수도 있다. 명시적인 수신이 있는 서비스는 구현에 따라 응답한다. 수신 서비스 자체는 다운스트림에서 “거부된 연결”을 처리하는 방법을 결정해야 한다. 로드 밸런서와 수신 모두에서 HTTP 503이 발생할 가능성이 높다.

또한 애플리케이션이 쿠버네티스 오토스케일링을 사용하는 경우 오토스케일링 구성에 따라 로드 밸런서에서 제거되는 애플리케이션에 다르게 반응할 수 있다.

애플리케이션 생명주기 및 프로브 상태(Application Lifecycle and Probe States)

쿠버네티스 프로브 지원의 중요한 측면은 애플리케이션 생명주기와 일관성이다. AvailabilityState(애플리케이션의 인 메모리 내부의 상태)와 실제 프로브(해당 상태를 노출함) 사이에는 상당한 차이가 있다. 애플리케이션 생명주기 단계에 따라 프로브를 사용하지 못할 수도 있습니다.

스프링 부트는 시작 및 종료 중에 애플리케이션 이벤트를 게시하고 프로브는 이러한 이벤트를 수신하고 AvailabilityState 정보를 노출할 수 있다.

다음 표는 AvailabilityState와 다양한 단계의 HTTP 커넥터 상태를 보여준다.

스프링 부트 애플리케이션이 시작될 때.

시작 단계LivenessStateReadinessStateHTTP server노트
StartingBROKENREFUSING_TRAFFICNot started쿠버네티스는 “활성” 프로브를 확인하고 시간이 너무 오래 걸리는 경우 애플리케이션을 재시작한다.
StartedCORRECTREFUSING_TRAFFIC애플리케이션 컨텍스트가 새로고침된다. 애플리케이션은 시작 작업을 수행하지만 아직 트래픽을 수신하지 않는다. 
ReadyCORRECTACCEPTING_TRAFFICAccepts requests시작 작업이 완료됐다. 애플리케이션이 트래픽을 수신하고 있다.

스프링 부트 애플리케이션이 종료될 때.

종료 단계Liveness StateReadiness StateHTTP server노트
RunningCORRECTACCEPTING_TRAFFICAccepts requests종료가 요청됐다.
Graceful shutdownCORRECTREFUSING_TRAFFICNew requests are rejected활성화되면 종료가 단계적으로 요청을 처리한다.
Shutdown completeN/AN/AServer is shut down애플리케이션 컨텍스트가 닫히고 애플리케이션이 종료된다.

쿠버네티스 디플로이먼트에 대한 자세한 내용은 쿠버네티스 컨테이너 생명 주기 장을 참고하자.

13.2.10. 애플리케션 정보(Application Information)

Application information exposes various information collected from all InfoContributor beans defined in your ApplicationContext. Spring Boot includes a number of auto-configured InfoContributor beans, and you can write your own.

자동 구성된 인포컨트리뷰터(Auto-configured InfoContributors)

적절한 경우 스프링은 다음 인포컨트리뷰터(InfoContributor) 빈을 자동 구성한다.

ID명칭설명전제조건
buildBuildInfoContributor빌드 정보를 노출한다.META-INF/build-info.properties 리소스.
envEnvironmentInfoContributor이름이 info..로 시작하는 Environment의 모든 프로퍼티를 노출한다.None.
gitGitInfoContributor깃 정보를 노출합니다.git.properties 리소스.
javaJavaInfoContributor자바 런타임 정보를 노출한다.None.
osOsInfoContributor운영 체제 정보를 노출한다.None.

개별 컨트리뷰터 활성화 여부는 management.info.<id>.enabled 프로퍼티에 의해 제어된다. 컨트리뷰터마다 전제조건과 노출 정보의 성격에 따라 이 프로퍼티에 대한 기본값이 다르다.

활성화를 나타내는 전제조건이 없으면 env, javaos 컨트리뷰터는 기본적으로 비활성화된다. 각각은 management.info.<id>.enabled 프로퍼티를 true로 설정하여 활성화할 수 있다.

buildgit 정보 컨트리뷰터는 기본적으로 활성화된다. 각각은 management.info.<id>.enabled 프로퍼티를 false로 설정하여 비활성화할 수 있다. 또는 일반적으로 기본적으로 활성화되어 있는 모든 컨트리뷰터를 비활성화하려면 management.info.defaults.enabled 프로퍼티를 false로 설정하자.

커스텀 애플리케이이션 정보(Custom Application Information)

env 컨트리뷰터가 활성화되면 info.* 스프링 프로퍼티스를 설정하여 info 엔드포인트에서 노출되는 데이터를 커스텀할 수 있다. info 키 아래의 모든 Environment 프로퍼티스는 자동으로 노출된다. 예를 들어 application.properties 파일에 다음 설정을 추가할 수 있다.

프로퍼티스(Properties)

info.app.encoding=UTF-8
info.app.java.source=17
info.app.java.target=17

Yaml

info: 
  app:
    encoding: "UTF-8"
    java:
      source: "17"
      target: "17"

TIP


해당 값을 하드코딩하는 대신 빌드 시 info 프로퍼티스를 확장할 수도 있다.

메이븐을 사용한다고 가정하면 이전 예제를 다음과 같이 재작성할 수 있다.

프로퍼티스(Properties)

info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@

Yaml

info: 
  app:
    encoding: "@project.build.sourceEncoding@"
    java:
      source: "@java.version@"
      target: "@java.version@"

깃 커밋 정보(Git Commit Information)

info 엔드포인트의 또 다른 유용한 기능은 프로젝트가 빌드될 때 깃 소스 코드 리포지터리의 상태에 대한 정보를 게시하는 기능이다. GitProperties 빈을 사용할 수 있는 경우 info 엔드포인트를 사용하여 이러한 프로퍼티스를 노출할 수 있다.

GitProperties 빈은 클래스패스의 루트에서 git.properties 파일을 사용할 수 있는 경우 자동으로 구성된다. 자세한 내용은 “깃 정보 생성 방법”을 참고하자.

기본적으로, 엔드포인트는 git.branch, git.commit.idgit.commit.time 프로퍼티를 노출한다. 엔드포인트 응답에서 이러한 프로퍼티스를 원하지 않는 경우 git.properties 파일에서 제외해야 한다. 전체 깃 정보(즉, git.properties의 전체 내용)를 표시하려면 다음과 같이 management.info.git.mode 프로퍼티를 사용하자.

프로퍼티스(Properties)

management.info.git.mode=full

Yaml

management:
  info:
    git:
      mode: "full"

info 엔드포인트에서 깃 커밋 정보를 완전히 비활성화하려면 다음과 같이 management.info.git.enabled 프로퍼티를 false로 설정한다.

프로퍼티스(Properties)

management.info.git.enabled=false

Yaml

management:
  info:
    git:
      enabled: false

빌드 정보(Build Information)

BuildProperties 빈을 사용할 수 있는 경우, info 엔드포인트는 빌드에 대한 정보를 게시할 수도 있다. 이는 클래스패스에 META-INF/build-info.properties 파일을 사용할 수 있는 경우다.

{. note} 메이븐과 그레이들 플러그인 모두 해당 파일을 생성할 수 있다. 자세한 내용은 “빌드 정보 생성 방법”을 참고하자.

자바 정보(Java Information)

info 엔드포인트는 자바 런타임 환경에 대한 정보를 제공한다. 자세한 내용은 JavaInfo를 참고하자. The info endpoint publishes information about your Java runtime environment, see JavaInfo for more details.

OS 정보(OS Information)

info 엔드포인트는 운영 체제에 대한 정보를 제공한다. 자세한 내용은 OsInfo를 참고하자.

커스텀 인포컨트리뷰터 개발(Writing Custom InfoContributors)

애플리케이션의 커스텀 정보를 제공하기 위해 InfoContributor 인터페이스를 구현하는 스프링 빈을 등록할 수 있다.

다음 예제에서는 example 항목의 한가지 값을 제공한다.

자바

import java.util.Collections;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;

@Component
public class MyInfoContributor implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("example", Collections.singletonMap("key", "value"));
    }
}

코틀린

import org.springframework.boot.actuate.info.Info
import org.springframework.boot.actuate.info.InfoContributor
import org.springframework.stereotype.Component
import java.util.Collections

@Component
class MyInfoContributor : InfoContributor {
  override fun contribute(builder: Info.Builder) {
      builder.withDetail("example", Collections.singletonMap("key", "value"))
  } 
}

info 엔드포인트에 도달하면, 다음 추가 항목이 포함된 응답이 표시된다.

If you reach the info endpoint, you should see a response that contains the following additional entry:

{
  "example": {
    "key" : "value"
  }
}

13.3. HTTP 모니터링과 관리(Monitoring and Management Over HTTP)

웹 애플리케이션을 개발하는 경우 스프링 부트 액추에이터는 활성화된 모든 엔드포인트가 HTTP를 통해 노출되도록 자동 구성한다. 기본 규칙은 /actuator 접두사가 있는 엔드포인트 ID를 URL 경로로 사용하는 것이다. 예를 들어 상태 정보는 /actuator/health로 노출된다.

액추에이터는 스프링 MVC, 스프링 웹플럭스 및 저지(Jersey)에서 기본적으로 지원된다. 저지와 스프링 MVC를 모두 사용할 수 있는 경우 스프링 MVC가 사용된다.

잭슨은 API 문서(HTML 또는 PDF)에 설명된 대로 올바른 JSON 응답을 얻기 위해 필요한 의존성이다.

13.3.1. 관리 엔드포인트 경로 커스텀(Customizing the Management Endpoint Paths)

경우에 따라 관리 엔드포인트의 접두사를 커스텀하는 것이 유용한 상황이 있다. 예를 들어 애플리케이션이 이미 다른 목적으로 /actuator를 사용하고 있을 수 있다. 다음 예제에 표시된 것처럼 management.endpoints.web.base-path 프로퍼티를 사용하여 관리 엔드포인트의 접두사를 변경할 수 있다.

프로퍼티스(Properties)

management.endpoints.web.base-path=/manage

Yaml

management:
  endpoints:
    web:
      base-path: "/manage"

이전 application.properties 예제에서는 엔드포인트를 /actuator/{id}에서 /manage/{id}(예: /manage/info)로 변경한다.

관리 포트가 다른 HTTP 포트를 사용하여 엔드포인트를 노출하도록 구성되지 않은 한, management.endpoints.web.base-pathserver.servlet.context-path(서블릿 웹 애플리케이션의 경우) 또는 spring.webflux.base-path에 상대적이다. (리액티브 웹 애플리케이션의 경우) management.server.port가 구성된 경우 management.endpoints.web.base-pathmanagement.server.base-path에 상대적이다.

엔드포인트를 다른 경로에 매핑하려면 management.endpoints.web.path-mapping 프로퍼티를 사용할 수 있다.

다음 예제에서는 /actuator/health/healthcheck로 다시 매핑한다.

프로퍼티스(Properties)

management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck

Yaml

management:
  endpoints:
    web:
      base-path: "/"
      path-mapping:
        health: "healthcheck"

13.3.2. 관리 서버 포트 커스텀(Customizing the Management Server Port)

기본 HTTP 포트를 사용하여 관리 엔드포인트를 노출하는 것은 클라우드 배포엔 적합한 선택이다. 그러나 애플리케이션이 자체 데이터 센터 내에서 실행되는 경우 다른 HTTP 포트를 사용하여 엔드포인트를 노출하는 것이 좋다.

다음 예제와 같이 management.server.port 프로퍼티를 설정하여 HTTP 포트를 변경할 수 있다.

프로퍼티스(Properties)

management.server.port=8081

Yaml

management:
  server:
    port: 8081

클라우드 파운드리에서 기본적으로 애플리케이션은 HTTP 및 TCP 라우팅 모두에 대해 포트 8080에서만 요청을 수신한다. 클라우드 파운드리에서 커스텀 관리 포트를 사용하려면 트래픽을 커스텀 포트로 전달하도록 애플리케이션의 경로를 명시적으로 설정해야 한다.

13.3.3. 관리별 SSL 구성(Configuring Management-specific SSL)

커스텀 포트를 사용하도록 구성한 경우 다양한 management.server.ssl.* 프로퍼티스를 사용하여 자체 SSL로 관리 서버를 구성할 수도 있다. 예를 들어, 이렇게 하면 다음 프로퍼티 설정에 표시된 것처럼 메인 애플리케이션이 HTTPS를 사용하는 동안 HTTP를 통해 관리 서버를 사용할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

또는, 메인 서버와 관리 서버 모두 SSL을 사용할 수 있지만 다음과 같이 키 저장소가 다르다.

프로퍼티스(Properties)

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

Yaml

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

13.3.4. 관리 서버 주소 커스텀(Customizing the Management Server Address)

management.server.address 프로퍼티를 설정하여 관리 엔드포인트를 사용할 수 있는 주소를 커스텀할 수 있다. 이렇게 하면 내부 또는 운영 네트워크에서만 수신 대기하거나 localhost의 연결만 수신하려는 경우 유용할 수 있다.

포트가 기본 서버 포트와 다른 경우에만 다른 주소에서 수신 대기할 수 있다.

다음 예제 application.properties는 원격 관리에 대한 커넥션을 허용하지 않는다.

프로퍼티스(Properties)

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

Yaml

management:
  server:
    port: 8081
    address: "127.0.0.1"

13.3.5. HTTP 엔드포인트 비활성화(Disabling HTTP Endpoints)

HTTP를 통해 엔드포인트를 노출하지 않으려면 다음 예제와 같이 관리 포트를 -1로 설정할 수 있다.

프로퍼티스(Properties)

management.server.port=-1

Yaml

management:
  server:
    port: -1

다음 예제에 표시된 것처럼 management.endpoints.web.exposure.exclude 프로퍼티를 사용하여 이를 달성할 수도 있다.

프로퍼티스(Properties)

management.endpoints.web.exposure.exclude=*

Yaml

management:
  endpoints:
    web:
      exposure:
        exclude: "*"

13.4. JMX를 통한 모니터링 및 관리(Monitoring and Management over JMX)

JMX(Java Management Extensions)는 애플리케이션을 모니터링하고 관리하는 표준 메커니즘을 제공한다. 기본적으로 이 기능은 활성화되어 있지 않다. spring.jmx.enabled 프로퍼티를 true로 설정하여 이를 켤 수 있다. 스프링 부트는 ID가 mbeanServer인 빈으로 가장 적합한 MBeanServer를 노출한다. 스프링 JMX 어노테이션(@ManagedResource, @ManagedAttribute 또는 @ManagedOperation)으로 어노테이션이 달린 모든 빈이 여기에 노출된다.

플랫폼이 표준 MBeanServer를 제공하는 경우 스프링 부트는 이를 사용하고 필요한 경우 VM MBeanServer를 기본값으로 사용한다. 모든 작업이 실패하면 새 MBeanServer가 생성된다.

자세한 내용은 JmxAutoConfiguration 클래스를 참고하자.

기본적으로 스프링 부트는 org.springframework.boot 도메인 아래에 JMX MBean으로 management 엔드포인트도 노출한다. JMX 도메인의 엔드포인트 등록을 완전히 제어하려면 자체 EndpointObjectNameFactory 구현체 등록을 고려해보자.

13.4.1. MBean 이름 커스텀(Customizing MBean Names)

MBean의 이름은 일반적으로 엔드포인트의 ID에서 생성된다. 예를 들어 상태(health) 엔드포인트는 org.springframework.boot:type=Endpoint,name=Health로 노출된다.

애플리케이션에 하나 이상의 스프링 애플리케이션컨텍스트(ApplicationContext)가 포함되어 있으면 이름이 충돌할 수 있다. 이 문제를 해결하려면 spring.jmx.unique-names 프로퍼티를 true로 설정하여 MBean 이름이 항상 고유하도록 할 수 있다.

엔드포인트가 노출되는 JMX 도메인을 커스텀할 수도 있다. 다음 설정은 application.properties에서 이를 수행하는 예제를 보여준다.

프로퍼티스(Properties)

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

Yaml

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

13.4.2. JMX 엔드포인트 비활성화(Disabling JMX Endpoints)

JMX를 통해 엔드포인트를 노출하지 않으려면 다음 예제에 표시된 대로 management.endpoints.jmx.exposure.exclude 프로퍼티를 *로 설정할 수 있다.

프로퍼티스(Properties)

management.endpoints.jmx.exposure.exclude=*

Yaml


management:
  endpoints:
    jmx:
      exposure:
        exclude: "*"

13.5. 옵저버블리티(Observability)

옵저버블리티는 실행 중인 시스템의 내부 상태를 외부에서 관찰하는 기능이다. 이는 로깅, 메트릭 및 트레이스의 세 가지로 구성된다.

메트릭 및 트레이스을 위해 스프링 부트는 마이크로미터 옵저베이션(Micrometer Observation)을 사용한다. 자체 옵저베이션을 생성하려면(메트릭 및 트레이스) ObservationRegistry를 주입할 수 있다.

import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.stereotype.Component;

@Component
public class MyCustomObservation {
  private final ObservationRegistry observationRegistry;

  public MyCustomObservation(ObservationRegistry observationRegistry) {
      this.observationRegistry = observationRegistry;
  }

  public void doSomething() {
      Observation.createNotStarted("doSomething", this.observationRegistry)
                  .lowCardinalityKeyValue("locale", "en-US")
                  .highCardinalityKeyValue("userId", "42")
                  .observe(() -> {
                    // Execute business logic here
                  });
  } 
}

낮은 카디널리티는 메트릭 및 트레이스에 추가되고, 높은 카디널리티는 트레이스에만 추가된다.

ObservationPredicate, GlobalObservationConventionObservationHandler 타입의 빈은 ObservationRegistry에 자동으로 등록된다. 추가로 ObservationRegistryCustomizer 빈을 등록하여 레지스트리를 추가로 구성할 수 있다.

자세한 내용은 마이크로미터 옵저베이션 문서를 참고하자.

JDBC 및 R2DBC에 대한 옵저버블리티는 별도의 프로젝트를 사용하여 구성할 수 있다. JDBC는 데이터소스 마이크로미터(Datasource Micrometer) 프로젝트에서 JDBC 작업이 호출될 때 자동으로 옵저베이션(observation)을 생성하는 스프링 부트 스타터를 제공한다. 레퍼런스 문서에서 이에 대한 자세한 내용을 읽어보자. R2DBC의 경우 R2DBC 옵저베이션을 위한 스프링부트 자동 구성은 R2DBC 쿼리 호출에 대한 옵저베이션을 생성한다.

다음 장에서는 로깅, 메트릭, 트레이스에 대한 자세한 내용을 제공한다.

13.6. 로거(Loggers)

스프링 부트 액추에이터에는 런타임 시 애플리케이션의 로그 레벨 확인 후 구성 기능이 포함되어 있다. 명시적으로 구성된 로깅 레벨과 로깅 프레임워크에서 제공하는 효과적인 로깅 레벨으로 구성된 전체 목록이나 개별 로거의 구성을 볼 수 있다. 이러한 레벨은 다음 중 하나다.

TRACEDEBUGINFOWARNERRORFATALOFFnull

null은 명시적인 구성이 없음을 나타낸다.

13.6.1. 로거 구성(Configure a Logger)

특정 로거를 구성하려면 다음 예제와 같이 리소스의 URI에 부분 엔터티를 게시한다.

{
  "configuredLevel": "DEBUG"
}

로거의 특정 레벨을 “재설정”하려면(그리고 기본 구성을 사용하려면)configureLevelnull 값을 전달할 수 있다.

13.7. 메트릭(Metrics)

스프링 부트 액추에이터는 다음을 내용들을 포함하여 수많은 모니터링 시스템을 지원하는 애플리케이션 메트릭 퍼사드(facade)인 마이크로미터(Micrometer)에 대한 의존성 관리 및 자동 구성을 제공한다.

  • 앱옵틱스(AppOptics)
  • 아틀라스(Atlas)
  • 데이터독(Datadog)
  • 다이나트레이스(Dynatrace)
  • 엘라스틱(Elastic)
  • 강글리아(Ganglia)
  • 그라파이트(Graphite)
  • 휴미오(Humio)
  • 인플럭스(Influx)
  • JMX
  • 카이로스DB(KairosDB)
  • 뉴 레릭(New Relic)
  • 오픈텔레메트리(OpenTelemetry)
  • 프로메테우스(Prometheus)
  • 시그널Fx(SignalFx)
  • 심플(Simple (in-memory))
  • 스택드라이버(Stackdriver)
  • 스태스디(StatsD)
  • 웨이브프론트(Wavefront)

마이크로미터(Micrometer)의 기능에 대해 자세히 알아보려면 해당 레퍼런스 문서, 특히 개념 장을 참고하자.

13.7.1. 시작하기(Getting started)

스프링 부트는 미터레지스트리(MeterRegistry)를 자동 구성하고 클래스패스에서 발견된 각 구현체에 대한 레지스트리를 추가한다. 런타임 클래스패스에 micrometer-registry-{system}에 대한 의존성이 있으면 스프링 부트가 레지스트리를 구성한다.

대부분의 레지스트리는 공통 기능(common feature)을 공유한다. 예를 들어 마이크로미터(Micrometer) 레지스트리 구현체가 클래스패스에 있는 경우에도 특정 레지스트리를 비활성화할 수 있다. 다음 예제에서는 데이터독(Datadog)을 비활성화한다.

프로퍼티스(Properties)

management.datadog.metrics.export.enabled=false

Yaml

management:
  datadog:
    metrics:
      export:
        enabled: false

다음 예제와 같이 레지스트리별 프로퍼티가 달리 명시되지 않는 한 모든 레지스트리를 비활성화할 수도 있다.

프로퍼티스(Properties)

management.defaults.metrics.export.enabled=false

Yaml

management:
  defaults:
    metrics:
      export:
        enabled: false

또한 스프링 부트는 명시적으로 지정하지 않는 한 자동 구성된 레지스트리를 메트릭(Metrics) 클래스의 전역 정적 복합(composite) 레지스트리에 추가한다.

프로퍼티스(Properties)

management.metrics.use-global-registry=false

Yaml

management:
  metrics:
    use-global-registry: false

미터가 레지스트리에 등록되기 전, 공통 태그 적용과 같은 레지스트리를 추가로 구성하기 위해 원하는 수의 미터레지스트리커스터마이저(MeterRegistryCustomizer) 빈을 등록할 수 있다.

자바

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

코틀린

import io.micrometer.core.instrument.MeterRegistry
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyMeterRegistryConfiguration {
  @Bean
  fun metricsCommonTags(): MeterRegistryCustomizer<MeterRegistry> {
    return MeterRegistryCustomizer { registry ->
        registry.config().commonTags("region", "us-east-1")
    }  
  }
}

제네릭 타입을 더 구체적으로 지정하여 특정 레지스트리 구현체에 커스텀을 적용할 수 있다.

자바

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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 ...
  } 
}

코틀린

import io.micrometer.core.instrument.Meter
import io.micrometer.core.instrument.config.NamingConvention
import io.micrometer.graphite.GraphiteMeterRegistry
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyMeterRegistryConfiguration {
  @Bean
  fun graphiteMetricsNamingConvention(): MeterRegistryCustomizer<GraphiteMeterRegistry> {
    return MeterRegistryCustomizer { registry: GraphiteMeterRegistry ->
      registry.config().namingConvention(this::name)
    } 
  }
    
  private fun name(name: String, type: Meter.Type, baseUnit: String?): String {
    return  ...
  } 
}

스프링 부트는 또한 구성 또는 전용 어노테이션 마커를 통해 제어할 수 있는 빌트인 기능을 구성한다.

13.7.2. 지원되는 모니터링 시스템(Supported Monitoring Systems)

이 절에서는 지원되는 각 모니터링 시스템에 대해 간략하게 설명한다.

앱옵틱스(AppOptics)

기본적으로 앱옵틱스(AppOptics) 레지스트리는 주기적으로 메트릭을 api.appoptics.com/v1/measurements에 푸시한다. 지표를 SaaS 앱옵틱스로 내보내려면 API 토큰을 제공해야 한다.

프로퍼티스(Properties)

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

Yaml

management:
  appoptics:
    metrics:
      export:
        api-token: "YOUR_TOKEN"

아틀라스(Atlas)

기본적으로 메트릭은 로컬 컴퓨터에서 실행되는 아틀라스(Atlas)로 보내진다. 아틀라스 서버의 위치를 ​​제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

데이터독(Datadog)

데이터독 레지스트리는 주기적으로 메트릭을 datadoghq에 푸시한다. 메트릭을 데이터독으로 내보내려면 API 키를 제공해야 한다.

프로퍼티스(Properties)

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

Yaml

management:
  datadog:
    metrics:
      export:
        api-key: "YOUR_KEY"

애플리케이션 키(선택 사항)를 추가로 제공하면 미터 설명, 유형, 기본 단위와 같은 메타데이터도 보낸다.

프로퍼티스(Properties)

management.datadog.metrics.export.api-key=YOUR_API_KEY
management.datadog.metrics.export.application-key=YOUR_APPLICATION_KEY

Yaml

management:
  datadog:
    metrics:
      export:
        api-key: "YOUR_API_KEY"
        application-key: "YOUR_APPLICATION_KEY"

기본적으로 메트릭은 데이터독 US 사이트(api.datadoghq.com)로 전송된다. 데이터독 프로젝트가 다른 사이트 중 하나에서 호스팅되거나 프록시를 통해 메트릭을 보내야 하는 경우 URI를 구성하자.

프로퍼티스(Properties)

management.datadog.metrics.export.uri=https://api.datadoghq.eu

Yaml

management:
  datadog:
    metrics:
      export:
        uri: "https://api.datadoghq.eu"

메트릭이 데이터옥으로 전송되는 간격을 변경할 수도 있다.

프로퍼티스(Properties)

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

Yaml

management:
  datadog:
    metrics:
      export:
        step: "30s"

다이나트레이스(Dynatrace)

다이나트레이스는 두 가지 메트릭 수집 API를 제공하며, 둘 다 마이크로미터(Micrometer)용으로 구현된다. 여기에서 마이크로미터 메트릭 수집에 대한 다이나트레이스(Dynatrace) 문서를 찾을 수 있다. v1 네임스페이스의 구성 프로퍼티스는 Timeseries v1 API로 내보낼 때만 적용된다. v2 네임스페이스의 구성 프로퍼티스는 Metrics v2 API로 내보낼 때만 적용된다. 이 인테그레이션(integration)은 한 번에 v1 또는 v2 버전의 API로만 내보낼 수 있으며 v2가 선호된다. v1 네임스페이스에 device-id(v1에는 필요하지만 v2에서는 사용되지 않음)가 설정된 경우 메트릭을 v1 엔드포인트로 내보낸다. 그렇지 않으면 v2로 내보낸다.

v2 API

v2 API는 두 가지 방법으로 사용할 수 있다.

Auto-configuration

다이나트레이스 자동 구성은 OneAgent 또는 쿠버네티스용 다이나트레이스 오퍼레이터(Operator)에서 모니터링하는 호스트에 사용할 수 있다.

Local OneAgent: OneAgent가 호스트에서 실행 중인 경우 메트릭은 자동으로 로컬 OneAgent ingest 엔드포인트로 보내진다. ingest 엔드포인트는 메트릭을 다이나트레이스 백엔드로 전달한다.

Dynatrace Kubernetes Operator: 다이나트레이스 오퍼레이터(Operator)가 설치된 쿠버네티스에서 실행할 때 레지스트리는 오퍼레이터가 엔드포인트 URI와 API 토큰을 자동으로 선택한다.

이는 기본 동작이며 io.micrometer:micrometer-registry-dynatrace에 대한 의존성 외에는 특별한 설정이 필요하지 않다.

Manual configuration

자동 구성을 사용할 수 없는 경우 Metrics v2 API의 엔드포인트와 API 토큰이 필요하다. API 토큰에는 “메트릭 수집”(metrics.ingest) 권한이 있어야 한다. 토큰의 범위를 이 권한 하나로 제한하는 것이 좋다. 엔드포인트 URI에 경로(예: /api/v2/metrics/ingest)가 포함되어 있는지 확인해야 한다.

Metrics API v2 ingest 엔드포인트의 URL은 디플로이먼트 옵션에 따라 다르다.

  • SaaS: https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest
  • Managed deployments: https://{your-domain}/e/{your-environment-id}/api/v2/metrics/ingest

아래 예제에서는 예제 환경 ID를 사용하여 메트릭 내보내기를 구성한다.

프로퍼티스(Properties)

management.dynatrace.metrics.export.uri=https://example.live.dynatrace.com/api/v2/metrics/ingest
management.dynatrace.metrics.export.api-token=YOUR_TOKEN

Yaml

management:
  dynatrace:
    metrics:
      export:
        uri: "https://example.live.dynatrace.com/api/v2/metrics/ingest"
        api-token: "YOUR_TOKEN"

Dynatrace v2 API를 사용할 때 다음과 같은 선택적 기능을 사용할 수 있다(자세한 내용은 다이나트레이스 문서에서 확인할 수 있다).

  • Metric key prefix: 내보낸 모든 메트릭 키 앞에 추가되는 접두사를 설정한다.
  • Enrich with Dynatrace metadata: OneAgent 또는 Dynatrace 오퍼레이터가 실행 중인 경우 추가 메타데이터(예: 호스트, 프로세스 또는 파트에 대한) 정보를 메트릭에 전달한다.
  • Default dimensions: 내보낸 모든 메트릭에 추가되는 키-값 쌍을 지정한다. 동일한 키를 가진 태그가 마이크로미터로 지정된 경우 기본 값을 덮어쓴다.
  • Use Dynatrace Summary instruments: 특정 상황에서 마이크로미터 다이나트레이스 레지스트리가 거부된 메트릭을 생성한다. 마이크로미터 1.9.x에서는 다이나트레이스 관련 요약 도구를 도입하여 이 문제를 해결했다. 이 토글을 false로 설정하면 마이크로미터가 1.9.x 이전의 기본값인 동작으로 되돌아간다. 마이크로미터 1.8.x에서 1.9.x로 마이그레이션하는 동안 문제가 발생할 때만 사용해야 한다.

다음 예제와 같이 URI 및 API 토큰을 지정하지 않을 수도 있다. 이 시나리오에서는 자동 구성 엔드포인트가 사용된다.

프로퍼티스(Properties)

management.dynatrace.metrics.export.v2.metric-key-prefix=your.key.prefix
management.dynatrace.metrics.export.v2.enrich-with-dynatrace-metadata=true
management.dynatrace.metrics.export.v2.default-dimensions.key1=value1
management.dynatrace.metrics.export.v2.default-dimensions.key2=value2
management.dynatrace.metrics.export.v2.use-dynatrace-summary-instruments=true

Yaml

management:
  dynatrace:
    metrics:
      export:
        # 로컬 OneAgent 엔드포인트를 사용하지 않는 경우 여기에 uri 및 api-token을 지정한다.
        v2:
          metric-key-prefix: "your.key.prefix"
          enrich-with-dynatrace-metadata: true
          default-dimensions:
            key1: "value1"
            key2: "value2"
          use-dynatrace-summary-instruments: true # (default: true)
v1 API (Legacy)

타이나트레이스 v1 API 메트릭 레지스트리는 Timeseries v1 API를 사용하여 주기적으로 구성된 URI에 지표를 전달한다. 기존 설정과의 이전 버전과의 호환성을 위해 device-id가 설정되면(v1에는 필요하지만 v2에서는 사용되지 않음) 메트릭을을 Timeseries v1 엔드포인트로 내보낸다. 메트릭을 다이나트레이스로 내보내려면 API 토큰, 장치 ID 및 URI를 제공해야 한다.

프로퍼티스(Properties)

management.dynatrace.metrics.export.uri=https://{your-environment-id}.live.dynatrace.com
management.dynatrace.metrics.export.api-token=YOUR_TOKEN
management.dynatrace.metrics.export.v1.device-id=YOUR_DEVICE_ID

Yaml

management:
  dynatrace:
    metrics:
      export:
        uri: "https://{your-environment-id}.live.dynatrace.com"
        api-token: "YOUR_TOKEN"
        v1:
          device-id: "YOUR_DEVICE_ID"

v1 API의 경우, v1 엔드포인트 경로가 자동으로 추가되므로 경로 없이 기본 환경 URI를 지정해야 한다.

Version-independent Settings

API 엔드포인트 및 토큰 외에도 지표가 다이나트레이스로 전송되는 간격을 변경할 수도 있다. 기본 전달 간격은 60초다. 다음 예제에서 전달 간격을 30초로 설정한다.

프로퍼티스(Properties)

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

Yaml

management:
  dynatrace:
    metrics:
      export:
        step: "30s"

마이크로미터 문서 및 다이나트레이스 문서에서 마이크로미터용 다이나트레이스 전달을 설정하는 방법에 대한 자세한 정보를 찾을 수 있다.

엘라스틱(Elastic)

기본적으로, 메트릭은 로컬 컴퓨터에서 실행되는 엘라스틱(Elastic)으로 보내진다. 다음 프로퍼티를 사용하여 엘라스틱 서버의 위치를 ​​제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

강글리아(Ganglia)

기본적으로 메트릭은 로컬 컴퓨터에서 실행되는 강글리아(Ganglia)로 보내진다. 다음 예제와 같이 강글리아(Ganglia) 서버 호스트 및 포트를 제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

그라파이트(Graphite)

기본적으로 메트릭은 로컬 시스템에서 실행되는 그라파이트(Graphite)로 보내진다. 다음 예제와 같이 그라파이트(Graphite) 서버 호스트 및 포트를 제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

마이크로미터(Micrometer)는 dimensional meter ID가 단순 계층 이름에 매핑되는 방식을 제어하는 ​​기본 HierarchicalNameMapper를 제공한다.


TIP

이 동작을 제어하려면 GraphiteMeterRegistry를 정의하고 고유한 HierarchicalNameMapper를 제공하자. 사용자가 직접 정의하지 않는 한 자동 구성된 GraphiteConfigClock 빈이 제공된다.

자바

import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.core.instrument.util.HierarchicalNameMapper;
import io.micrometer.graphite.GraphiteConfig;
import io.micrometer.graphite.GraphiteMeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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 ... 
  }
}

코틀린

import io.micrometer.core.instrument.Clock
import io.micrometer.core.instrument.Meter
import io.micrometer.core.instrument.config.NamingConvention
import io.micrometer.core.instrument.util.HierarchicalNameMapper
import io.micrometer.graphite.GraphiteConfig
import io.micrometer.graphite.GraphiteMeterRegistry
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyGraphiteConfiguration {
  @Bean
  fun graphiteMeterRegistry(config: GraphiteConfig, clock: Clock): GraphiteMeterRegistry {
    return GraphiteMeterRegistry(config, clock, this::toHierarchicalName)
  }
  
  private fun toHierarchicalName(id: Meter.Id, convention: NamingConvention): String {
    return ... 
  }
}

휴미오(Humio)

기본적으로, 휴미오(Humio) 레지스트리는 주기적으로 메트릭을 cloud.humio.com에 전달한다. 메트릭을 SaaS 휴미오로 보내려면 API 토큰을 제공해야 한다.

프로퍼티스(Properties)

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

Yaml

management:
  humio:
    metrics:
      export:
        api-token: "YOUR_TOKEN"

또한 메트릭이 푸시되는 데이터 소스를 식별하기 위해 하나 이상의 태그를 구성해야 한다.

프로퍼티스(Properties)

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

Yaml

management:
  humio:
    metrics:
      export:
        tags:
          alpha: "a"
          bravo: "b"

인플럭스(Influx)

기본적으로 메트릭은 기본 구성을 사용하여 로컬 컴퓨터에서 실행되는 Influx v1 인스턴스로 보내진다. 메트릭을 InfluxDB v2로 내보내려면 메트릭 작성을 위한 조직(org), 버킷 및 인증 토큰을 구성해야한다. 다음을 사용하여 인플럿트 서버의 위치를 ​​제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

JMX

마이크로미터(Micrometer)는 주로 메트릭을 로컬에서 볼 수 있는 간단하고 이식 가능한 방법으로 JMX에 대한 계층적 매핑을 제공한다. 기본적으로 메트릭은 메트릭 JMX 도메인으로 보내진다. 다음을 사용하여 도메인을 제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

management:
  jmx:
    metrics:
      export:
        domain: "com.example.app.metrics"

마이크로미터는 dimensional meter ID가 단순 계층 이름에 매핑되는 방식을 제어하는 ​​기본 HierarchicalNameMapper를 제공한다.


이 동작을 제어하려면 JmxMeterRegistry를 정의하고 고유한 HierarchicalNameMapper를 제공하자. 사용자가 직접 정의하지 않는 한 자동 구성된 JmxConfigClock 빈이 제공된다.

자바

import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.core.instrument.util.HierarchicalNameMapper;
import io.micrometer.jmx.JmxConfig;
import io.micrometer.jmx.JmxMeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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 ... 
  }
}

코틀린

import io.micrometer.core.instrument.Clock
import io.micrometer.core.instrument.Meter
import io.micrometer.core.instrument.config.NamingConvention
import io.micrometer.core.instrument.util.HierarchicalNameMapper
import io.micrometer.jmx.JmxConfig
import io.micrometer.jmx.JmxMeterRegistry
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyJmxConfiguration {
  @Bean
  fun jmxMeterRegistry(config: JmxConfig, clock: Clock): JmxMeterRegistry {
      return JmxMeterRegistry(config, clock, this::toHierarchicalName)
  }
  
  private fun toHierarchicalName(id: Meter.Id, convention: NamingConvention): String {
    return ... 
  }
}


카이로스DB(KairosDB)

기본적으로, 메트릭은 로컬 시스템에서 실행되는 카이로스DB(KairosDB)로 보내진다. 다음을 사용하여 사용할 카이로스DB(KairosDB) 서버의 위치를 ​​제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

뉴 레릭(New Relic)

뉴 레릭 레지스트리는 주기적으로 메트릭을 뉴 레릭에 전달한다. 메트릭을 뉴 레릭으로 보내려면 API 키와 계정 ID를 제공해야 한다.

프로퍼티스(Properties)

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

Yaml

management:
  newrelic:
    metrics:
      export:
        api-key: "YOUR_KEY"
        account-id: "YOUR_ACCOUNT_ID"

You can also change the interval at which metrics are sent to New Relic:

프로퍼티스(Properties)

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

Yaml

management:
  newrelic:
    metrics:
      export:
        step: "30s"

기본적으로, 메트릭은 REST 호출을 통해 전달되지만 클래스패스에 Java Agent API가 있는 경우 이를 사용할 수도 있다.

프로퍼티스(Properties)

management.newrelic.metrics.export.client-provider-type=insights-agent

Yaml

management:
  newrelic:
    metrics:
      export:
        client-provider-type: "insights-agent"

마지막으로, 자신만의 NewRelicClientProvider 빈을 정의하여 완전한 제어권을 가질 수 있다.

오픈텔레메트리(OpenTelemetry)

기본적으로, 메트릭은 로컬 컴퓨터에서 실행되는 오픈텔레메트리(OpenTelemetry)로 보내진다. 다음을 사용하여 사용할 오픈텔레메트리 메트릭 엔드포인트의 위치를 ​​제공할 수 있다.

프로퍼티스(Properties)

management.otlp.metrics.export.url=https://otlp.example.com:4318/v1/metrics

Yaml

management:
  otlp:
    metrics:
      export:
        url: "https://otlp.example.com:4318/v1/metrics"

프로메테우스(Prometheus)

프로메테우스(Prometheus)는 메트릭을 위해 개별 애플리케이션 인스턴스를 스크래핑(scrape)하거나 폴링(poll)할 것을 예상한다. 스프링 부트는 프로메테우스 스크레이프를 적절한 타입으로 제공하기 위해 /actuator/prometheus에 액추에이터 엔드포인트를 제공한다.

기본적으로, 엔드포인트는 사용할 수 없으며 노출되어야 한다. 자세한 내용은 엔드포인트 노출을 참고하자.

다음 예제 scrape_configprometheus.yml에 추가된다.

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

프로메테우스 Exemplars도 지원된다. 이 기능을 활성화하려면 SpanContextSupplier 빈이 있어야 한다. Micrometer Tracing을 사용하면 자동 구성되지만 원하는 경우 언제든지 직접 만들 수 있다. 이 기능은 프로메테우스 측에서 명시적으로 활성화해야 하며 오픈메트릭(OpenMetrics) 타입을 통해서만 지원되므로 프로메테우스 문서를 확인하자.

스크랩할 만큼 오래 존재하지 않는 임시 또는 배치 잡의 경우 프로메테우스 Pushgateway을 사용하여 프로메테우스에 메트릭을 노출할 수 있다. 프로메테우스 Pushgateway 지원을 활성화하려면 프로젝트에 다음 의존성을 추가하자.

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

프로메테우스 Pushgateway 의존성이 클래스패스에 존재하고 management.prometheus.metrics.export.pushgateway.enabled 프로퍼티가 true로 설정되면 PrometheusPushGatewayManager 빈이 자동 구성된다. 이는 프로메테우스 Pushgateway에 대한 메트릭 푸시를 관리한다.

management.prometheus.metrics.export.pushgateway 아래의 프로퍼티스를 사용하여 PrometheusPushGatewayManager를 조정할 수 있다. 고급 구성의 경우 자체 PrometheusPushGatewayManager 빈을 제공할 수도 있다.

시그널Fx(SignalFx)

시그널Fx 레지스트리는 주기적으로 메트릭을 시그널Fx에 전달한다. 메트릭을 시그널Fx로 보내려면 액세스 토큰을 제공해야 한다.

프로퍼티스(Properties)

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

Yaml

management:
  signalfx:
    metrics:
      export:
        access-token: "YOUR_ACCESS_TOKEN"

메트릭이 시그널Fx 전송되는 간격(interval)을 변경할 수도 있다.

프로퍼티스(Properties)

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

Yaml

management:
  signalfx:
    metrics:
      export:
        step: "30s"

심플(Simple)

마이크로미터는 다른 레지스트리가 구성되지 않은 경우 대체 수단으로 사용되는 간단한 인메모리 백엔드를 함께 제공한다. 이를 통해 메트릭 엔드포인트에서 수집되는 메트릭을 확인할 수 있다.

사용 가능한 다른 백엔드를 사용하는 즉시 인메모리 백엔드는 자동으로 비활성화된다. 명시적으로 비활성화할 수도 있다.

프로퍼티스(Properties)

management.simple.metrics.export.enabled=false

Yaml

management:
  simple:
    metrics:
      export:
        enabled: false

스택드라이버(Stackdriver)

스택드라이버(Stackdriver) 레지스트리는 주기적으로 메트릭을 스택드라이버에 푸시한다. 메트릭을 SaaS 스택드라이버로 내보내려면 구글 클라우드 프로젝트 ID를 제공해야 한다.

프로퍼티스(Properties)

management.stackdriver.metrics.export.project-id=my-project

Yaml

management:
  stackdriver:
    metrics:
      export:
        project-id: "my-project"

메트릭이 스택드라이버(Stackdriver)로 전송되는 간격을 변경할 수도 있다.

프로퍼티스(Properties)

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

Yaml

management:
  stackdriver:
    metrics:
      export:
        step: "30s"

스태스디(StatsD)

스태스디(StatsD) 레지스트리는 UDP를 통해 메트릭을 스태스디 에이전트에 적극적으로 푸시한다. 기본적으로 메트릭은 로컬 시스템에서 실행되는 스태스디 에이전트로 보내진다. 다음을 사용하여 사용할 스태스디 에이전트 호스트, 포트 및 프로토콜을 제공할 수 있다.

프로퍼티스(Properties)

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

Yaml

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

사용할 스태스디(StatsD) 라인 프로토콜을 변경할 수도 있다(기본값은 데이터독이다).

프로퍼티스(Properties)

management.statsd.metrics.export.flavor=etsy

Yaml

management:
  statsd:
    metrics:
      export:
        flavor: "etsy"

웨이브프론트(Wavefront)

웨이브프론트 레지스트리는 주기적으로 메트릭을 웨이브프론트에 전달한다. 메트릭을 웨이브프론트로 직접 보내는 경우 API 토큰을 제공해야 한다.

프로퍼티스(Properties)

management.wavefront.api-token=YOUR_API_TOKEN

Yaml

management:
  wavefront:
    api-token: "YOUR_API_TOKEN"

또는 사용자 환경에서 웨이브프론트(Wavefront) 사이드카 또는 내부 프록시를 사용하여 메트릭 데이터를 웨이브프론트 API 호스트에 전달할 수 있다.

프로퍼티스(Properties)

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

Yaml

management:
  wavefront:
    uri: "proxy://localhost:2878"

웨이브프론트 문서에 설명된 대로 메트릭을 웨이브프론트 프록시에 게시하는 경우 호스트는 proxy://HOST:PORT 형식이어야 한다.

메트릭이 웨이브프론트로 전송되는 간격을 변경할 수도 있다.

프로퍼티스(Properties)

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

Yaml

management:
  wavefront:
    metrics:
      export:
        step: "30s"

13.7.3. 메트릭 및 미터 지원(Supported Metrics and Meters)

스프링 부트는 다양한 기술에 대한 미터(meter) 자동 등록을 제공한다. 대부분 상황에서 기본값은 지원되는 모니터링 시스템에 게시할 수 있는 메트릭을 제공한다.

JVM 메트릭(JVM Metrics)

자동 구성을 사용하면 코어 마이크로미터(Micrometer) 클래스를 사용하여 JVM 메트릭를 사용할 수 있다. JVM 메트릭은 jvm. 미터명 아래에 게시된다.

다음 JVM 메트릭이 제공된다.

  • 다양한 메모리 및 버퍼 풀 세부 정보
  • 가비지 수집 관련 통계
  • 스레드 활용도
  • 로드 및 언로드된 클래스 수
  • JVM 버전 정보
  • JIT 컴파일 시간

시스템 메트릭(System Metrics)

자동 구성은 코어 마이크로미터 클래스를 사용하여 시스템 메트릭을 활성화한다. 시스템 메트릭은 system., process.disk. 미터명 아래에 게시된다.

다음과 같은 시스템 메트릭이 제공된다.

  • CPU 메트릭
  • 파일 디스크립터 메트릭
  • 가동 시간 메트릭(애플리케이션이 실행된 시간과 절대 시작 시간의 고정 게이지)
  • 사용 가능한 디스크 공간(Disk space available)

애플리케이션 시작 메트릭(Application Startup Metrics)

자동 구성은 애플리케이션 시작 시간 메트릭을 노출한다.

  • application.started.time: 애플리케이션을 시작하는 데 걸린 시간이다.
  • application.ready.time: 애플리케이션이 요청을 처리할 준비가 되는 데 걸리는 시간이다.

메트릭은 애플리케이션 클래스의 정규화된 이름으로 태그가 지정된다.

로거 메트릭(Logger Metrics)

자동 구성 시 로그백(Logback) 및 Log4J2 모두 이벤트 메트릭이 활성화된다. 세부 정보는 log4j2.events 또는 logback.events. 미터명에 게시된다.

작업 실행 및 스케줄링 메트릭(Task Execution and Scheduling Metrics)

자동 구성 시 기본 ThreadPoolExecutor를 사용가능하면 모든 ThreadPoolTaskExecutorThreadPoolTaskScheduler 빈을 측정할 수 있다. 메트릭은 빈 이름에서 파생된 익스큐터명으로 태그가 지정된다.

스프링 MVC 메트릭(Spring MVC Metrics)

자동 구성 시 스프링 MVC 컨트롤러 및 기능 핸들러가 처리하는 모든 요청을 측정할 수 있다. 기본적으로 메트릭은 http.server.requests라는 이름으로 생성된다. management.observations.http.server.requests.name 프로퍼티를 설정하여 이름을 커스텀할 수 있다.

생성된 옵저베이션에 대한 자세한 내용은 스프링 프레임워크 레퍼런스 문서를 참고하자.

기본 태그에 추가하려면 org.springframework.http.server.observation 패키지에서 DefaultServerRequestObservationConvention을 확장하는 @Bean을 제공하자. 기본 태그를 바꾸려면 ServerRequestObservationConvention을 구현하는 @Bean을 제공하자.

어떤 경우, 웹 컨트롤러에서 처리된 예외가 요청 메트릭 태그로 기록되지 않는다. 애플리케이션은 처리된 예외를 요청 애트리뷰트로 설정하여 예외를 선택하고 기록할 수 있다.

기본적으로, 모든 요청이 처리된다. 필터를 커스텀하려면 FilterRegistrationBean<WebMvcMetricsFilter>를 구현하는 @Bean을 제공하자.

스프링 웹플럭스 메트릭(Spring WebFlux Metrics)

자동 구성 시 스프링 웹플럭스 컨트롤러 및 펑셔널(functional) 핸들러가 처리하는 모든 요청을 측정할 수 있다. 기본적으로 메트릭은 http.server.requests라는 이름으로 생성된다. management.observations.http.server.requests.name 프로퍼티를 설정하여 이름을 커스텀할 수 있다.

생성된 옵저베이션에 대한 자세한 내용은 스프링 프레임워크 레퍼런스 문서를 참고하자.

기본 태그에 추가하려면 org.springframework.http.server.reactive.observation 패키지에서 DefaultServerRequestObservationConvention을 확장하는 @Bean을 제공하자. 기본 태그를 바꾸려면 ServerRequestObservationConvention을 구현하는 @Bean을 제공하자.

경우에 따라, 컨트롤러 및 핸들러 함수에서 처리된 예외가 요청 메트릭 태그로 기록되지 않는다. 애플리케이션은 처리된 예외를 요청 애트리뷰트로 설정하여 예외를 선택하고 기록할 수 있다.

저지 서버 메트릭(Jersey Server Metrics)

자동 구성을 사용하면 저지 JAX-RS 구현에서 처리하는 모든 요청을 측정할 수 있다. 기본적으로 메트릭은 http.server.requests로 생성된다. management.observations.http.server.requests.name 프로퍼티를 설정하여 이름을 커스텀할 수 있다.

기본적으로, 저지 서버 메트릭에는 다음 정보가 태그로 지정된다.

태그설명
exception요청을 처리하는 동안 발생한 예외의 클래스명이다.
method요청 메서드(예: GET 또는 POST)
outcome응답의 상태 코드를 기반으로 한 요청의 결과다. 1xx는 정보, 2xx는 성공, 3xx는 리디렉션, 4xxCLIENT_ERROR, 5xxSERVER_ERROR다.
status응답의 HTTP 상태 코드(예: 200 또는 500)
uri변수 대체 전 요청의 URI 템플릿(예: /api/person/{id})

태그를 커스텀하려면 JerseyTagsProvider를 구현하는 @Bean을 제공하자.

HTTP 클라이언트 메트릭(HTTP Client Metrics)

스프링부트 액추에이터는 레스트템플릿(RestTemplate)과 웹클라이언트(WebClient)의 측정을 관리한다. 이를 위해서는 자동 구성된 빌더를 주입하여 인스턴스를 생성해야 한다.

  • RestTemplate을 위한 RestTemplateBuilder
  • WebClient를 위한 WebClient.Builder

이 측정을 담당하는 커스터마이저(customizer), 즉 ObservationRestTemplateCustomizerObservationWebClientCustomizer를 수동으로 적용할 수도 있다.

기본적으로, 메트릭은 http.client.requests라는 이름으로 생성된다. management.observations.http.client.requests.name 프로퍼티를 설정하여 이름을 커스텀할 수 있다.

생성된 옵저베이션에 대한 자세한 내용은 스프링 프레임워크 레퍼런스 문서를 참고하자.

레스트템플릿(RestTemplate)을 사용할 때 태그를 커스텀하려면 org.springframework.http.client.observation 패키지에서 ClientRequestObservationConvention을 구현하는 @Bean을 제공하자. 웹클라이언트(WebClient)를 사용할 때 태그를 커스텀하려면 org.springframework.web.reactive.function.client 패키지에서 ClientRequestObservationConvention을 구현하는 @Bean을 제공하자.

톰캣 메트릭(Tomcat Metrics)

자동 구성은 MBeanRegistry가 활성화된 경우에만 톰캣의 측정을 활성화한다. 기본적으로 MBeanRegistry는 비활성화되어 있지만 server.tomcat.mbeanregistry.enabledtrue로 설정하여 활성화할 수 있다.

톰캣 메트릭은 tomcat. 미터명 아래 게시된다.

캐시 메트릭(Cache Metrics)

자동 구성을 사용하면 시작 시 사용 가능한 모든 캐시 인스턴스를 측정할 수 있으며, 메트릭 앞에 캐시가 붙는다. 캐시 측정은 기본 메트릭 집합에 대해 표준화되어 있다. 추가적인 캐시별 메트릭도 사용할 수 있다.

다음 캐시 라이브러리가 지원된다.

  • Cache2k
  • Caffeine
  • Hazelcast
  • Any compliant JCache (JSR-107) implementation
  • Redis

메트릭은 캐시 이름과 빈 이름에서 파생된 CacheManager 이름으로 태그가 지정된다.

시작 시 구성된 캐시만 레지스트리에 바인딩된다. 즉석에서 생성되거나 시작 단계 이후 프로그래밍 방식으로 생성된 캐시와 같이 캐시 구성에 정의되지 않은 캐시의 경우 명시적인 등록이 필요하다. 해당 프로세스를 더 쉽게 만들기 위해 CacheMetricsRegistrar 빈을 사용할 수 있다.

스프링 배치 메트릭(Spring Batch Metrics)

스프링 배치 레퍼런스 문서를 참고하자.

스프링 그래프QL 메트릭(Spring GraphQL Metrics)

스프링 그래프QL 레퍼런스 문서를 참고하자.

데이터소스 메트릭(DataSource Metrics)

자동 구성을 사용하면 jdbc.connections라는 접두어가 붙은 메트릭을 사용하여 사용 가능한 모든 DataSource 객체를 측정할 수 있다. 데이터 원본 측정을 통해 풀에서 현재 활성(active), 유휴(idle), 최대 허용(maximum allowed) 및 최소 허용(minimum allowed) 커넥션을 나타내는 게이지가 생성된다.

메트릭에는 빈 이름을 기반으로 계산된 DataSource 이름으로 태그가 지정된다.

기본적으로, 스프링부트는 지원되는 모든 데이터 소스에 대한 메타데이터를 제공한다. 즐겨찾는 데이터 소스가 지원되지 않는 경우 추가 DataSourcePoolMetadataProvider 빈을 추가할 수 있다. 예제는 DataSourcePoolMetadataProvidersConfiguration을 참고하자.

또한, 히카리(Hikari) 관련 메트릭은 hikaricp 접두사로 노출된다. 각 지표에는 풀(pool) 이름으로 태그가 지정된다(spring.datasource.name으로 제어할 수 있음).

하이버네이트 메트릭(Hibernate Metrics)

org.hibernate.orm:hibernate-micrometer가 클래스패스에 있으면 통계가 활성화되어있는 모든 하이버네이트 EntityManagerFactory 인스턴스는 hibernate라는 메트릭으로 측정된다.

메트릭에는 빈 이름에서 파생된 EntityManagerFactory 이름으로 태그가 지정된다.

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

프로퍼티스(Properties)

spring.jpa.properties[hibernate.generate_statistics]=true

Yaml

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

스프링 데이터 리포지터리 메트릭(Spring Data Repository Metrics)

자동 구성을 사용하면 모든 스프링 데이터 리포지터리 메서드 호출을 측정할 수 있다. 기본적으로 메트릭은 spring.data.repository.invocations라는 이름으로 생성된다. management.metrics.data.repository.metric-name 프로퍼티를 설정하여 이름을 커스텀할 수 있다.

io.micrometer.core.annotation 패키지의 @Timed 어노테이션은 리포지터리 인터페이스 및 메서드에서 지원된다. 모든 리포지터리 호출에 대한 지표를 기록하지 않으려면 management.metrics.data.repository.autotime.enabledfalse로 설정하고 대신 @Timed 어노테이션을 독점적으로 사용할 수 있다.

longTask = true@Timed 어노테이션은 해당 메서드에 대해 긴 작업 타이머를 활성화한다. 긴 작업 타이머에는 별도의 메트릭명이 필요하며 짧은 작업 타이머와 함께 누적될 수 있다.

기본적으로, 리포지터리 호출 관련 메트릭에는 다음 정보가 태그로 지정된다.

태그설명
repository소스 리포지터리의 간단한 클래스명이다.
method호출된 리포지터리 메서드명이다.
state결과 상태(SUCCESS, ERROR, CANCELED 또는 RUNNING).
exception호출에서 발생한 예외의 간단한 클래스명이다.

기본 태그를 바꾸려면 RepositoryTagsProvider를 구현하는 @Bean을 제공하자.

래빗MQ 메트릭(RabbitMQ Metrics)

자동 구성을 사용하면 rabbitmq라는 메트릭을 사용하여 사용 가능한 모든 RabbitMQ 커넥션 팩토리를 측정할 수 있다.

스프링 인테그레이션 메트릭(Spring Integration Metrics)

스프링 인테그레이션은 메트릭리포지터리(MeterRegistry) 빈을 사용할 수 있을 때마다 자동으로 마이크로미터 지원을 제공한다. 메트릭은 spring.integration 미터명 아래에 게시된다.

카프카 메트릭(Kafka Metrics)

자동 구성은 자동 구성된 소비자 팩토리와 생산자 팩토리에 대해 각각 MicrometerConsumerListenerMicrometerProducerListener를 등록한다. 또한 StreamsBuilderFactoryBean에 대한 KafkaStreamsMicrometerListener를 등록합니다. 자세한 내용은 스프링 카프카 설명서의 마이크로미터 네이티브 메트릭 장을 참고하자.

몽고DB 메트릭(MongoDB Metrics)

이 장에서는 몽고DB에 사용 가능한 메트릭을 간략하게 설명한다.

몽고DB 커맨드 메트릭(MongoDB Command Metrics)

자동 구성은 자동 구성된 몽고클라이언트(MongoClient)몽고메트릭커멘드리스너(MongoMetricsCommandListener)를 등록한다.

기본 몽고DB 드라이버에 실행된 각 명령에 대해 mongodb.driver.commands라는 타이머 메트릭이 생성된다. 각 지표에는 기본적으로 다음 정보가 태그로 지정된다.

태그설명
command실행된 명령의 이름이다.
cluster.id명령이 전송된 클러스터의 식별자다.
server.address명령이 전송된 서버의 주소다.
status명령의 결과(SUCCESS 또는 FAILED)다.

기본 메트릭 태그를 바꾸려면, 다음 예제와 같이 몽고커멘드태그프로바이더(MongoCommandTagsProvider) 빈을 정의한다.

자바

import io.micrometer.core.instrument.binder.mongodb.MongoCommandTagsProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyCommandTagsProviderConfiguration {
  @Bean
  public MongoCommandTagsProvider customCommandTagsProvider() {
      return new CustomCommandTagsProvider();
  }
}

코틀린

import io.micrometer.core.instrument.binder.mongodb.MongoCommandTagsProvider
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyCommandTagsProviderConfiguration {
  @Bean
  fun customCommandTagsProvider(): MongoCommandTagsProvider? {
      return CustomCommandTagsProvider()
  }
}

자동 구성된 커멘드 메트릭을 비활성화하려면 다음 프로퍼티를 설정하자.

프로퍼티스(Properties)

management.metrics.mongo.command.enabled=false

Yaml

management:
  metrics:
    mongo:
      command:
        enabled: false
몽고DB 커넥션 풀 메트릭(MongoDB Connection Pool Metrics)

자동 구성은 자동 구성된 몽고클라이언트(MongoClient)몽고메트릭커넥션풀리스너(MongoMetricsConnectionPoolListener)를 등록한다.

커넥션 풀에 대해 다음 게이지 메트릭이 생성된다.

  • mongodb.driver.pool.size는 유휴(idle) 멤버와 사용 중인(in-use) 멤버를 포함하여 커넥션 풀의 현재 크기를 보고한다.
  • mongodb.driver.pool.checkedout은 현재 사용 중인 커넥션 수를 보고한다.
  • mongodb.driver.pool.waitqueuesize는 풀의 커넥션에 대한 대기열의 현재 크기를 보고한다.

각 메트릭에는 기본적으로 다음 정보가 태그로 지정된다.

태그설명
cluster.id커넥션 풀이 해당하는 클러스터의 식별자다.
server.address커넥션 풀이 해당하는 서버의 주소다.

기본 메트릭 ㄴ태그를 바꾸려면 MongoConnectionPoolTagsProvider 빈을 정의한다.

자바

import io.micrometer.core.instrument.binder.mongodb.MongoConnectionPoolTagsProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyConnectionPoolTagsProviderConfiguration {
  @Bean
  public MongoConnectionPoolTagsProvider customConnectionPoolTagsProvider() {
    return new CustomConnectionPoolTagsProvider();
  }
}

코틀린

import io.micrometer.core.instrument.binder.mongodb.MongoConnectionPoolTagsProvider
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyConnectionPoolTagsProviderConfiguration {
    @Bean
    fun customConnectionPoolTagsProvider(): MongoConnectionPoolTagsProvider {
        return CustomConnectionPoolTagsProvider()
    }
}

자동 구성된 커넥션 풀 메트릭을 비활성화하려면 다음 프로퍼티를 설정하자.

프로퍼티스(Properties)

management.metrics.mongo.connectionpool.enabled=false

Yaml

management:
  metrics:
    mongo:
      connectionpool:
        enabled: false

제티 메트릭(Jetty Metrics)

자동 구성은 마이크로미터의 제티서버스레드풀메트릭(JettyServerThreadPoolMetrics)를 사용하여 제티의 스레드풀에 대한 메트릭을 바인딩한다. 제티의 커넥터 인스턴스에 대한 메트릭은 마이크로미터의 제티커넥션메트릭(JettyConnectionMetrics)를 사용하고 server.ssl.enabledtrue로 설정된 경우 마이크로미터의 제티Ssl핸드쉐이크메트릭(JettySslHandshakeMetrics)를 사용하여 바인딩된다.

@Timed 어노테이션 지원(@Timed Annotation Support)

스프링 부트에서 직접 지원되지 않는 @Timed를 사용하려면 마이크로미터 문서를 참고하자.

레디스 메트릭(Redis Metrics)

자동 구성은 자동 구성된 LettuceConnectionFactory에 대해 MicrometerCommandLatencyRecorder를 등록한다. 자세한 내용은 Lettuce 문서의 마이크로미터 메트릭 장을 참고하자.

13.7.4. 커스텀 메트릭 등록(Registering Custom Metrics)

커스텀 메트릭을 등록하려면 MeterRegistry를 컴포넌트에 주입하자.

자바

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;
import org.springframework.stereotype.Component;

@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());
  }
}

코틀린

import io.micrometer.core.instrument.MeterRegistry
import io.micrometer.core.instrument.Tags
import org.springframework.stereotype.Component

@Component
class MyBean(registry: MeterRegistry) {
  private val dictionary: Dictionary
  init {
    dictionary = Dictionary.load()
    registry.gauge("dictionary.size", Tags.empty(), dictionary.words.size)
  } 
}

메트릭이 다른 빈에 의존하는 경우, 미터바인더(MeterBinder)를 사용하여 등록하는 것이 좋다.

자바

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.context.annotation.Bean;

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

코틀린

import io.micrometer.core.instrument.Gauge
import io.micrometer.core.instrument.binder.MeterBinder
import org.springframework.context.annotation.Bean

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

미터바인더(MeterBinder)를 사용하면 올바른 의존 관계가 설정되고 메트릭 값을 검색할 때 빈을 사용할 수 있다. 미터바인더(MeterBinder) 구현은 컴포넌트나 애플리케이션 전체에 걸쳐 일련의 메트릭을 반복적으로 계측하는 경우에도 유용할 수 있다.

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

13.7.5. 개별 메트릭 커스텀(Customizing Individual Metrics)

특정 미터(Meter) 인스턴스를 커스텀해야 하는 경우 io.micrometer.core.instrument.config.MeterFilter 인터페이스를 사용할 수 있다.

예를 들어, com.example로 시작하는 모든 미터 ID에 대해 mytag.region 태그의 이름을 mytag.area로 바꾸려면 다음을 수행하면 된다.

자바

import io.micrometer.core.instrument.config.MeterFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyMetricsFilterConfiguration {
  @Bean
  public MeterFilter renameRegionTagMeterFilter() {
    return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
  }
}

코틀린

import io.micrometer.core.instrument.config.MeterFilter
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyMetricsFilterConfiguration {
  @Bean
  fun renameRegionTagMeterFilter(): MeterFilter {
    return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area")
  }
}

기본적으로, 모든 미터필터(MeterFilter) 빈은 스프링이 관리하는 미터레지스트리(MeterRegistry)에 자동 바인딩된다. 메트릭(Metrics)의 정적 메서드가 아닌 스프링이 관리하는 미터레지스트리(MeterRegistry)를 사용하여 메트릭을 등록해야 한다. 이는 스프링이 관리하지 않는 전역 레지스트리를 사용한다.

공통 태그(Common Tags)

공통 태그는 일반적으로 host, instance, region, stack 등과 같은 운영 환경에 대한 차원 드릴다운에 사용된다. Commons 태그는 모든 미터에 적용되며 다음 예제와 같이 구성될 수 있다.

프로퍼티스(Properties)

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

Yaml

management:
  metrics:
    tags:
      region: "us-east-1"
      stack: "prod"

앞의 예제에서는 각각 값이 us-east-1prod인 모든 미터에 regionstack 태그를 추가한다.

Graphite를 사용하는 경우 공통 태그의 순서가 중요하다. 이 접근 방식을 사용하면 공통 태그의 순서를 보장할 수 없으므로 Graphite 사용자는 대신 커스텀 MeterFilter를 정의하는 것이 좋다.

미터별 프로퍼티(Per-meter Properties)

MeterFilter 빈 외에도 프로퍼티스를 사용하여 미터별로 제한된 커스텀 세트를 적용할 수 있다. 스프링 부트의 PropertiesMeterFilter를 사용하여 지정된 이름으로 시작하는 모든 미터 ID에 미터별 커스텀이 적용된다. 다음 예제에서는 ID가 example.remote로 시작하는 모든 미터를 필터링한다.

프로퍼티스(Properties)

management.metrics.enable.example.remote=false

Yaml

management:
    metrics:
      enable:
        example:
          remote: false

다음 프로퍼티는 미터당 커스텀을 허용한다.

테이블 9. 미터당 커스텀

프로퍼티설명
management.metrics.enable특정 ID를 가진 미터를 허용할지 여부다. 허용되지 않는 미터는 MeterRegistry에서 필터링된다.
management.metrics.distribution.percentiles-histogram집계 가능한(차원 전체) 백분위수 근사치를 계산하는 데 적합한 히스토그램을 게시할지 여부다.
management.metrics.distribution.minimum-expected-value, management.metrics.distribution.maximum-expected-value예상 값의 범위를 고정하여 더 적은 수의 히스토그램 버킷을 게시한다.
management.metrics.distribution.percentiles애플리케이션에서 계산된 백분위수 값을 게시한다
management.metrics.distribution.expiry, management.metrics.distribution.buffer-length구성 가능한 버퍼 길이를 사용하여 구성 가능한 만료 후 회전하는 링 버퍼에 샘플을 누적하여 최근 샘플에 더 큰 가중치를 부여한다.
management.metrics.distribution.slo서비스 레벨 오브젝트에 따라 정의된 버킷이 포함된 누적 히스토그램을 게시한다.

백분위수(히스토그램, 백분위수 및 slo)의 개념에 대한 자세한 내용은 마이크로미터 문서의 “히스토그램 및 백분위수” 장을 참고하자.

13.7.6. 메트릭 엔드포인트(Metrics Endpoint)

스프링 부트는 애플리케이션에서 수집한 메트릭을 진단 및 검사하기 위해 사용할 수 있는 메트릭 엔드포인트를 제공한다. 엔드포인트는 기본적으로 사용할 수 없으며 무조건 노출되어야 한다. 자세한 내용은 엔드포인트 노출을 참고하자.

/actuator/metrics로 이동하면 사용 가능한 미터명 목록이 나타난다. 이름을 셀렉터로 제공하여 특정 미터에 대한 정보를 드릴다운하여 볼 수 있다(예: /actuator/metrics/jvm.memory.max).

여기서 사용하는 이름은 코드가 배송되는 모니터링 시스템에 대해 표준화된 명명 규칙 이후의 이름이 아니라 코드에 사용된 이름과 일치해야 한다. 즉, jvm.memory.max가 스네이크 케이스 명명 규칙으로 인해 프로메테우스(Prometheus)에서 jvm_memory_max로 나타나는 경우에도 메트릭 엔드포인트에서 미터를 검사할 때 jvm.memory.max를 셀렉터로 사용해야 한다.

또한 URL 끝에 원하는 수의 tag=KEY:VALUE 쿼리 파라미터를 추가하여 미터를 차원적으로 드릴다운할 수도 있다(예: /actuator/metrics/jvm.memory.max?tag=area:nonheap).

보고된 측정값은 미터 이름과 적용된 모든 태그와 일치하는 모든 미터의 통계 합이다. 앞의 예제에서 반환된 Value 통계는 힙의 “코드 캐시”, “압축 클래스 공간” 및 “메타 공간” 영역의 최대 메모리 공간의 합계다. “메타공간”의 최대 크기만 보려면 추가 tag=id:Metaspace, 즉 /actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace를 추가할 수 있다.

13.7.7. 마이크로미터 옵저베이션과의 통합(Integration with Micrometer Observation)

DefaultMeterObservationHandler는 완료된 모든 옵저베이션에 대한 지표를 생성하는 ObservationRegistry에 자동으로 등록된다.

13.8. 트레이싱(Tracing)

스프링 부트 액추에이터는 널리 사용되는 트레이서(tracer) 라이브러리의 퍼사드인 마이그로미터 트래이싱(Micrometer Tracing)에 대한 의존성 관리 및 자동 구성을 제공한다.

마이크로미터 트레이싱 기능에 대해 자세히 알아보려면 해당 레퍼런스 문서를 참고하자.

13.8.1. 트레이서 지원(Supported Tracers)

스프링 부트는 다음 트레이서에 대한 자동 구성을 제공한다.

13.8.2. 시작하기(Getting Started)

트레이싱을 시작하는 데 사용할 수 있는 예제 애플리케이션이 필요하다. 우리의 목적을 위해, 간단한 “Hello World!” “첫 번째 스프링 부트 애플리케이션 개발” 장에서 다룬 웹 애플리케이션이면 충분하다. 우리는 집킨(Zipkin)과 오픈텔레메트리(OpenTelemetry) 트레이서를 트레이스 백엔드로 사용할 것이다.

요약하면, 메인 애플리케이션 코드는 다음과 같다.

자바

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class MyApplication {

  private static final Log logger = LogFactory.getLog(MyApplication.class);

  @RequestMapping("/")
  String home() {
    logger.info("home() has been called");
    return "Hello World!";
  }

  public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
  } 
}

home() 메서드에 추가된 logger 문이 있는데, 이는 나중에 중요해진다.

이제 다음 의존성을 추가해야 한다.

  • org.springframework.boot:spring-boot-starter-actuator
  • io.micrometer:micrometer-tracing-bridge-otel - 마이크로미터 옵저베이션(Micrometer Observation) API를 오픈텔레메트리(OpenTelemetry)에 연결한다.
  • io.opentelemetry:opentelemetry-exporter-zipkin - traces을 집킨(Zipkin)에 전달한다.

다음 애플리케이션 프로퍼티스을 추가한다.

프로퍼티스(Properties)

management.tracing.sampling.probability=1.0

Yaml

management:
  tracing:
    sampling:
      probability: 1.0

기본적으로, 스프링 부트는 트레이스 백엔드가 과도해지는 것을 방지하기 위해 요청의 10%만 샘플링한다. 이 프로퍼티는 모든 요청이 트레이스 백엔드로 전송되도록 이를 100%로 전환한다.

트레이스를 수집하고 시각화하려면 실행 중인 트레이스 백엔드가 필요하다. 여기서 트레이스 백엔드로 집킨(Zipkin)을 사용한다. 집킨(Zipkin) 빠른 시작 가이드는 집킨(Zipkin)을 로컬에서 시작하는 방법에 대한 지침을 제공한다.

집킨(Zipkin)이 실행된 후 애플리케이션을 시작할 수 있다.

localhost:8080에 대한 웹 브라우저를 열면 다음 출력이 표시된다.

Hello World!

뒤에서는, HTTP 요청에 대한 옵저베이션이 생성됐으며, 이는 오픈텔레메트리(OpenTelemetry)에 연결되어 집킨(Zipkin)에 새로운 트레이스를 보고한다.

이제 localhost:9411에서 집킨(Zipkin) UI를 열고 “Run Query” 버튼을 눌러 수집된 모든 트레이스를 나열한다. 하나의 트레이스가 표시되어야 한다. 해당 추적의 세부정보를 보려면 “Show” 버튼을 누르자.

log.pattern.level 프로퍼티를 %5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]로 설정하여 로그에 현재 트레이스 및 범위 ID를 포함할 수 있다.

13.8.3. 트레이서 구현체(Tracer Implementations)

마이크로미터 트레이서(Micrometer Tracer)는 여러 트레이서 구현체을 지원하므로 스프링 부트에서는 여러 의존성 조합이 가능하다.

모든 트레이서 구현에는 org.springframework.boot:spring-boot-starter-actuator 의존성이 필요하다.

집킨과 오픈텔레메트리(OpenTelemetry With Zipkin)

오픈텔레메트리(OpenTelemetry)를 사용하여 트레이싱하고 집킨(Zipkin)에 보고하려면 다음 의존성이 필요하다.

  • io.micrometer:micrometer-tracing-bridge-otel - 마이크로미터 옵저베이션(Micrometer Observation) API를 오픈텔레메트리(OpenTelemetry)에 연결한다.
  • io.opentelemetry:opentelemetry-exporter-zipkin - 집킨(Zipkin)에 트레이스를 보고힌다.

집킨(Zipkin)에 대한 보고를 구성하려면 management.zipkin.tracing.* 프로퍼티스를 사용하자.

웨이브프론트와 오픈텔레메트리(OpenTelemetry With Wavefront)

오픈텔레메트리(OpenTelemetry)를 사용하여 트레이싱하고 웨이브프론트(Wavefront)에 보고하려면 다음 의존성이 필요하다.

  • io.micrometer:micrometer-tracing-bridge-otel - 마이크로미터 옵저베이션(Micrometer Observation) API를 오픈텔레메트리(OpenTelemetry)에 연결한다.
  • io.micrometer:micrometer-tracing-reporter-wavefront - 웨이브프론트(Wavefront)에 트레이싱을 보고한다.

웨이브프론트(Wavefront)를 사용하여 보고를 구성하려면 management.wavefront.* 프로퍼티스를 사용하자.

OTLP와 오픈텔레메트리(OpenTelemetry With OTLP)

오픈텔레메트리(OpenTelemetry)를 사용하여 트레이싱하고 OTLP를 사용하여 보고하려면 다음 의존성이 필요하다.

  • io.micrometer:micrometer-tracing-bridge-otel - 마이크로미터 옵저베이션(Micrometer Observation) API를 오픈텔레메트리(OpenTelemetry)에 연결한다.
  • io.opentelemetry:opentelemetry-exporter-otlp - OTLP를 허용할 수 있는 콜렉터에 트레이스을 보고한다.

OTLP를 사용하여 보고를 구성하려면 management.otlp.tracing.* 프로퍼티스를 사용하자.

오픈집킨 브레이브와 집킨(OpenZipkin Brave와 Zipkin)

오픈집킨 브레이브(OpenZipkin Brave)를 사용하여 트레이싱하고 집킨(Zipkin)에 보고하려면 다음 의존성이 필요하다.

  • io.micrometer:micrometer-tracing-bridge-brave - 마이크로미터 옵저베이션(Micrometer Observation) API를 브레이브(Brave)에 연결한다.
  • io.zipkin.reporter2:zipkin-reporter-brave - 집킨(Zipkin)에 트레이스를 보고한다.

프로젝트에서 스프링 MVC 또는 스프링 웹플럭스를 사용하지 않는 경우 io.zipkin.reporter2:zipkin-sender-urlconnection 의존성도 필요하다.

management.zipkin.tracing.* 프로퍼티스를 사용하여 집킨(Zipkin)에 대한 보고를 구성한다.

웨비으프론트와 오픈잡킨(BraveOpenZipkin Brave With Wavefront)

오픈집킨 브레이브(OpenZipkin Brave)를 사용하여 트레이싱하고 웨이브프론트(Wavefront)에 보고하려면 다음 의존성이 필요하다.

  • io.micrometer:micrometer-tracing-bridge-brave - 마이크로미터 옵저베이션(Micrometer Observation) API를 브레이브(Brave)에 연결한다.
  • io.micrometer:micrometer-tracing-reporter-wavefront - 웨이브프론트(Wavefront)에 트레이스를 보고한다.

management.wavefront.* 프로퍼티스를 사용하여 웨이브프론트(Wavefront)에 대한 보고를 구성한다.

13.8.4. 마이크로미터 옵저베이션과 통합(Integration with Micrometer Observation)

TracingAwareMeterObservationHandler는 완료된 모든 옵저베이션에 대한 범위를 생성하는 ObservationRegistry에 자동으로 등록된다.

13.8.5. 커스텀 스팬 만들기(Creating Custom Spans)

옵저베이션을 시작하여 고유한 스팬을 만들 수 있다. 이를 위해 ObservationRegistry를 컴포넌트에 주입한다.

import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.stereotype.Component;

@Component
class CustomObservation {
  private final ObservationRegistry observationRegistry;

  CustomObservation(ObservationRegistry observationRegistry) {
      this.observationRegistry = observationRegistry;
  }
  
  void someOperation() {
    Observation observation = Observation.createNotStarted("some-operation", this.observationRegistry);
      observation.lowCardinalityKeyValue("some-tag", "some-value");
      observation.observe(() -> {
          // 비즈니스 로직 ...
      });
  } 
}

그러면 “some-tag=some-value” 태그가 있는 “some-option”이라는 옵저베이션이 생성된다.

메트릭를 생성하지 않고 스팬를 생성하려면, 마이크로미터(Micrometer)의 하위 레벨 트레이서(Tracer) API를 사용해야 한다.

13.9. 오디팅(Auditing)

스프링 시큐리티(Spring Security)가 작동되면 스프링 부트 액추에이터(Spring Boot Actuator)는 이벤트(기본적으로 “인증 성공”, “실패” 및 “액세스 거부” 예외)를 게시하는 유연한 오디팅 프레임워크(audit framework)를 갖는다. 이 기능은 인증 실패에 따른 잠금 정책을 보고하고 구현하는 데 매우 유용할 수 있다.

애플리케이션 구성에 AuditEventRepository 타입의 빈을 제공하여 오디팅를 활성화할 수 있다. 편의를 위해 스프링 부트 InMemoryAuditEventRepository를 제공한다. InMemoryAuditEventRepository는 기능이 제한되어 있으므로 개발 환경에만 사용하는 것이 좋다. 프로덕션 환경의 경우 대체용 AuditEventRepository 구현체을 만드는 것이 좋다.

13.9.1. 커스텀 오디팅(Custom Auditing)

게시된 보안 이벤트를 커스텀하려면 AbstractAuthenticationAuditListenerAbstractAuthorizationAuditListener의 자체 구현을 제공할 수 있다.

귀하의 비즈니스 이벤트에 대한 오디팅 서비스를 사용할 수도 있다. 이렇게 하려면 AuditEventRepository 빈을 자체 컴포넌트에 주입하고 이를 직접 사용하거나 (ApplicationEventPublisherAware 구현을 통해) 스프링 ApplicationEventPublisherAuditApplicationEvent를 게시하자.

13.10. HTTP 교환 기록(Recording HTTP Exchanges)

애플리케이션 구성에 HttpExchangeRepository 타입의 빈을 제공하여 HTTP 교환 기록을 활성화할 수 있다. 편의를 위해 스프링 부트는 기본적으로 마지막 100개의 요청-응답 교환을 저장하는 InMemoryHttpExchangeRepository를 제공한다. InMemoryHttpExchangeRepository는 트레이싱 솔루션에 비해 제한적이므로 개발 환경에서만 사용하는 것이 좋다. 프로덕션 환경의 경우 집킨(Zipkin) 또는 오픈텔레메트리(OpenTelemetry)와 같은 프로덕션용 트레이싱 또는 옵저버블리티 솔루션을 사용하는 것이 좋다. 또는 자체 HttpExchangeRepository를 만들 수도 있다.

httpexchanges 엔드포인트를 사용하여 HttpExchangeRepository에 저장된 요청-응답 교환에 대한 정보를 얻을 수 있다.

13.10.1. 커스텀 HTTP 교환 기록(Custom HTTP Exchange Recording)

기록된 각 교환에 포함된 항목을 커스텀하려면 management.httpexchanges.recording.include 프로퍼티를 사용하자.

기록을 완전히 비활성화하려면, management.httpexchanges.recording.enabledfalse로 설정하자.

13.11. 프로세스 모니터링(Process Monitoring)

spring-boot 모듈에서는 프로세스 모니터링에 유용한 파일을 생성하는 두 가지 클래스를 찾을 수 있다.

  • ApplicationPidFileWriter는 애플리케이션 PID가 포함된 파일을 생성한다(기본적으로 파일명이 application.pid인 애플리케이션 디렉토리에 있음).
  • WebServerPortFileWriter는 실행 중인 웹 서버의 포트를 포함하는 파일(들)을 생성한다 (기본적으로 파일명이 application.port인 애플리케이션 디렉토리에 있음).

기본적으로, 이러한 라이터(writer)는 활성화되지 않지만 활성화할 수 있다.

  • 구성 확장을 통해
  • 프로그래밍 방식으로 프로세스 모니터링 활성화

13.11.1. 구성 확장(Extending Configuration)

META-INF/spring.factories 파일에서 PID 파일을 작성하는 리스너(또는 리스너)를 활성화할 수 있다.

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

13.11.2. 프로그래밍 방식으로 프로세스 모니터링 활성화(Programmatically Enabling Process Monitoring)

SpringApplication.addListeners(...) 메소드를 호출하고 적절한 라이터(Writer) 객체를 전달하여 리스너를 활성화할 수도 있다. 이 방법을 사용하면 Writer객체의 생성자에서 파일명과 경로를 커스텀할 수도 있다.

13.12. 클라우드 파운드리 지원(Cloud Foundry Support)

스프링 부트 액추에이터 모듈에는 호환되는 클라우드 파운드리(Cloud Foundry) 인스턴스에 배포할 때 활성화되는 추가 지원이 포함되어 있다. /cloudfoundryapplication 경로는 모든 @Endpoint 빈에 대한 대체 보안 경로를 제공한다.

확장된 지원을 통해 클라우드 파운드리(Cloud Foundry) 관리 UI(예: 배포된 애플리케이션을 보는 데 사용할 수 있는 웹 애플리케이션)를 스프링 부트 액추에이터 정보로 강화할 수 있다. 예를 들어 애플리케이션 상태 페이지에는 일반적인 “실행 중” 또는 “중지됨” 상태 대신 전체 상태 정보가 포함될 수 있다.

/cloudfoundryapplication 경로는 일반 사용자가 직접 접근할 수 없다. 엔드포인트를 사용하려면 요청과 함께 유효한 UAA 토큰을 전달해야 한다.

13.12.1. 확장 클라우드 파운드리 액추에이터 지원 비활성화(Disabling Extended Cloud Foundry Actuator Support)

/cloudfoundryapplication 엔드포인트를 완전히 비활성화하려면 application.properties 파일에 다음 설정을 추가하면 된다.

프로퍼티스(Properties)

management.cloudfoundry.enabled=false

Yaml

management:
  cloudfoundry:
    enabled: false

13.12.2. 클라우드 파운드리 자체 서명 인증서(Cloud Foundry Self-signed Certificates)

기본적으로 /cloudfoundryapplication 엔드포인트에 대한 보안 확인은 다양한 클라우드 파운드리(Cloud Foundry) 서비스에 대한 SSL 호출을 수행한다. 클라우드 파운드리 UAA 또는 클라우드 컨트롤러(Cloud Controller) 서비스가 자체 서명된 인증서를 사용하는 경우 다음 프로퍼티를 설정해야 한다.

프로퍼티스(Properties)

management.cloudfoundry.skip-ssl-validation=true

Yaml

management:
  cloudfoundry:
    skip-ssl-validation: true

13.12.3. 커스텀 컨텍스트 패스(Custom Context Path)

서버의 컨텍스트 패스가 / 이외의 다른 것으로 구성된 경우 애플리케이션 루트에서 클라우드 파운드리(Cloud Foundry) 엔드포인트를 사용할 수 없다. 예를 들어, server.servlet.context-path=/app인 경우 클라우드 파운드리(Cloud Foundry) 엔드포인트는 /app/cloudfoundryapplication/*에서 사용할 수 있다.

서버의 컨텍스트 패스에 관계없이 /cloudfoundryapplication/*에서 클라우드 파운드리(Cloud Foundry) 엔드포인트를 항상 사용할 수 있을 것으로 예상하는 경우 이를 애플리케이션에서 명시적으로 구성해야 한다. 사용 중인 웹 서버에 따라 구성이 다르다. 톰캣의 경우 다음 구성을 추가할 수 있다.

자바

import java.io.IOException;
import java.util.Collections;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.apache.catalina.Host;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCloudFoundryConfiguration {

  @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 (classes, 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("/*");
    };
  }
}

코틀린

import jakarta.servlet.GenericServlet
import jakarta.servlet.Servlet
import jakarta.servlet.ServletContainerInitializer
import jakarta.servlet.ServletContext
import jakarta.servlet.ServletException
import jakarta.servlet.ServletRequest
import jakarta.servlet.ServletResponse
import org.apache.catalina.Host
import org.apache.catalina.core.StandardContext
import org.apache.catalina.startup.Tomcat.FixContextListener
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.servlet.ServletContextInitializer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.io.IOException
import java.util.Collections.emptySet

@Configuration(proxyBeanMethods = false)
class MyCloudFoundryConfiguration {
  @Bean
  fun servletWebServerFactory(): TomcatServletWebServerFactory {
    return object : TomcatServletWebServerFactory() {
      override fun prepareContext(host: Host, initializers: Array<ServletContextInitializer>) {
        super.prepareContext(host, initializers)
        val child = StandardContext()
        child.addLifecycleListener(FixContextListener())
        child.path = "/cloudfoundryapplication"
        val initializer = getServletContextInitializer(contextPath)
        child.addServletContainerInitializer(initializer, emptySet())
        child.crossContext = true
        host.addChild(child)
      }
    } 
  }
    
  private fun getServletContextInitializer(contextPath: String): ServletContainerInitializer {
    return ServletContainerInitializer { classes: Set<Class<*>?>?, context: ServletContext ->
      val servlet: Servlet = object : GenericServlet() {
        @Throws(ServletException::class, IOException::class)
        override fun service(req: ServletRequest, res: ServletResponse) {
          val servletContext = req.servletContext.getContext(contextPath)
          servletContext.getRequestDispatcher("/cloudfoundryapplication").forward(req, res)
        }
      }
      
      context.addServlet("cloudfoundry", servlet).addMapping("/*")
    }
  }
}

그라파이트(Graphite)와 같은 그래프 도구에 대해 읽어보고 싶을 수도 있다.

그렇지 않으면 계속해서 “배포 옵션”에 대해 읽어보거나 스프링 부트의 빌드 도구 플러그인에 대한 심층적인 정보를 얻을 수 있다.