스프링 부트 핵심 가이드
[스프링 부트 핵심 가이드] Chapter 11장. 액추에이터 활용하기
스프링 부트 액추에이터는 HTTP 엔드포인트나 JMX를 활용하여 어플리케이션을 모니터링하고 관리할 수 있는 기능을 제공한다
- JMX (Java Management Extensions)는 자바에서 어플리케이션의 상태를 모니터링하고 설정을 변경할 수 있게 해주는 API다
- MBeans (Managed Beans)를 생성해야 한다
아래와 같이 spring-boot-starter-actuator 모듈의 종속성을 추가한다
- SwaggerConfiguration 클래스를 가져오고 그에 따른 의존성을 추가해야 한다
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
엔드포인트
Actuator의 엔드포인트는 어플리케이션의 모니터링을 사용하는 경로다
- 스프링 부트에는 여러 내장 엔드포인트가 포함되어 있고, 커스텀 엔드포인트를 추가할 수 있다
Actuator를 추가하면 기본적으로 엔드포인트 URL로 /actuator가 추가되고, 뒤에 경로를 추가해 상세 내역에 접근한다
아래와 같이 /actuator가 아닌 다른 경로를 사용하고 싶을 때, application.properties 파일에 작성할 수 있는 내용이다
management.endpoints.web.base-path=/custom-path
자주 활용되는 엔드포인트
ID | 설명 |
---|---|
auditevents | 호출된 Audit 이벤트 정보를 표시한다. AuditEventRepository 빈이 필요하다 |
beans | 어플리케이션에 있는 모든 스프링 빈 리스트를 표시한다 |
caches | 사용 가능한 캐시를 표시한다 |
conditions | 자동 구성 조건 내역을 생성한다 |
configprops | @ConfigurationProperties의 속성 리스트를 표시한다 |
env | 어플리케이션에서 사용할 수 있는 환경 속성을 표시한다 |
health | 어플리케이션의 상태 정보를 표시한다 |
httptrace | 가장 최근에 이루어진 100건의 요청 기록을 표시한다. HttpTraceRepository 빈이 필요하다 |
info | 어플리케이션의 정보를 표시한다 |
integrationgraph | 스프링 통합 그래프를 표시한다. spring-integration-core 모듈에 대한 의존성을 추가해야 동작한다 |
loggers | 어플리케이션의 로거 구성을 표시하고 수정한다 |
metrics | 어플리케이션의 메트릭 정보를 표시한다 |
mappings | 모든 @RequestMapping의 매핑 정보를 표시한다 |
quartz | Quartz 스케줄러 작업에 대한 정보를 표시한다 |
scheduledtasks | 어플리케이션에서 예약된 작업을 표시한다 |
sessions | 스프링 세션 저장소에서 사용자의 세션을 검색하고 삭제할 수 있다. 스프링 세션을 사용하는 서블릿 기반 웹 어플리케이션이 필요하다 |
shutdown | 어플리케이션을 정상적으로 종료할 수 있다. 기본값은 비활성화 상태다 |
startup | 어플리케이션이 시작될 때 수집된 시작 단계 데이터를 표시한다. BufferingApplicationStartup으로 구성된 스프링 어플리케이션이 필요하다 |
threaddump | 스레드 덤프를 수행한다 |
Spring MVC, Spring Webflux, Jersey를 사용하면 추가로 엔드포인트를 사용할 수 있다
ID | 설명 |
---|---|
heapdump | 힙 덤프 파일을 반환한다. 핫스팟(HotSpot) VM 상에서 hprof 포맷의 파일이 반환되며, OpenJ9JVM에서는 PHD 포맷 파일을 반환한다 |
jolokia | Jolokia가 클래스패스에 있을 때 HTTP를 통해 JMX 빈을 표시한다. jolokia-core 모듈에 대한 의존성 추가가 필요하며, WebFlux에서는 사용할 수 있다 |
logfile | logging.file.name 또는 logging.file.path 속성이 설정돼 있는 경우 로그 파일의 내용을 반환한다 |
Prometheus | Prometheus 서버에서 스크랩할 수 있는 형식으로 메트릭을 표시한다. micrometer-registry-prometheus 모듈의 의존성 추가가 필요하다 |
엔드포인트 활성화 여부 & 노출 여부
# application.properties
# 활성화 여부
management.endpoint.shutdown.enabled=true
management.endpoint.caches.enabled=true
# 노출 여부 (엔드포인트를 전체적으로 노출하되, threaddump와 heapdump는 제외한다)
# HTTP 설정
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=threaddump,heapdump
# JMX 설정
management.endpoints.jmx.exposure.include=*
management.endpoints.jmx.exposure.exclude=threaddump,heapdump
Actuator 기능
어플리케이션 기본 정보 (/info)
- 가동 중인 어플리케이션의 정보를 볼 수 있다
- 어플리케이션에서 몇 가지 방법을 거쳐 제공할 수도 있으나 application.properties 파일에서 'info.'로 시작하는 속성 값들을 정의하는 것이 제일 쉽다
# application.properties
# actuator info 정보 설정
info.organization.name=wikibooks
info.contact.email=joon@gmail.com
info.contact.phoneNumber=010-1234-1234
- 어플리케이션 가동 후 GET http://localhost/8080/actuator/info에 접근하면 아래와 같은 결과 값이 나온다 (물론 JSON 형태로 바꿔야 한다)
# 예시
{
"organization":
{
"name": "wikibooks"
},
"contact":
{
"email" : "joon@gmail.com",
"phoneNumber" : "010-1234-1234"
}
}
어플리케이션 상태 (/health)
- 설정 없이 GET http://localhost/8080/actuator/health 에 접근하면 된다
{"status" : "UP"}
- UP | DOWN | UNKNOWN | OUT_OF_SERVICE
- 주로 네트워크 계층 중 L4 (LoadBalancing) 레벨에서 어플리케이션의 상태를 확인하기 위해 사용된다
- 상세 상태 확인
- never(기본값) : 세부 사항은 표시하지 않는다
- when-authorized : 승인된 사용자에게만 세부 상태를 표시한다. application.properties에 추가한 management.endpoint.health.roles 속성으로 부여할 수 있다
- always : 모든 사용자에게 세부 상태를 표시한다
# application.properties
management.endpoint.health.show-details=always
- 상세 상태 확인 결과 값
# 예시
{
"status" : "UP",
"components" : {
"diskSpace" : {
"status" : "UP",
"details" : {
"total" : 536818479104,
"free" : 419451326464,
"threshold" : 1085760,
"exists" : true
}
},
"ping" : {
"status" : "UP"
}
}
}
빈 정보 확인 (/beans)
- 스프링 컨테이너에 등록된 스프링 빈의 전체 목록을 표시할 수 있다
- 워낙 많은 빈이 자동으로 등록되어 운영되어 내용을 출력해서 육안으로 내용을 파악하기 어렵다
- GET http://localhost/8080/actuator/beans 로 접근하면 된다
# 예시
{
"contexts" : {
"application" : {
"beans" : {
"endpointCachingOperationInvokerAdvisor" : {
"aliases" :[],
"scope" : "singleton",
"type" : "org.springframework......"
},
"parentId" : null
}
}
}
}
스프링 부트의 자동설정 내역 확인 (/conditions)
- 스프링 부트의 자동설정 (AutoConfiguration) 조건 내역을 확인한다
- GET http://localhost/8080/actuator/condition
# 예시
{
"contexts": {
"application-1": {
"positiveMatches": {
"AuditAutoConfiguration#auditListener": [
{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.audit.listener.AbstractAuditListener; SearchStrategy: all) did not find any beans"
}
],
"AuditAutoConfiguration#authenticationAuditListener": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required class 'org.springframework.security.authentication.event.AbstractAuthenticationEvent'; @ConditionalOnMissingClass did not find unwanted class"
},
{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.security.AbstractAuthenticationAuditListener; SearchStrategy: all) did not find any beans"
}
],
"AuditAutoConfiguration#authorizationAuditListener": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required class 'org.springframework.security.access.event.AbstractAuthorizationEvent'; @ConditionalOnMissingClass did not find unwanted class"
},
{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.security.AbstractAuthorizationAuditListener; SearchStrategy: all) did not find any beans"
}
],
...
스프링 환경변수 정보 (/env)
- 스프링의 환경변수 정보를 확인할 때 사용된다
- 기본적으로 application.properties 파일의 변수들이 표시되며, OS, JVM의 환경변수도 함께 표시된다
- GET http://localhost/8080/actuator/env
- 민감한 정보를 가리기 위해서는 management.endpoint.env.keys-to-snitize 속성을 사용하면 된다
{
"activeProfiles": [
],
"propertySources": [
{
"name": "server.ports",
"properties": {
"local.server.port": {
"value": 8080
}
}
},
{
"name": "mongo.ports",
"properties": {
"local.mongo.port": {
"value": 56240
}
}
},
{
"name": "servletContextInitParams",
"properties": {
}
},
{
"name": "systemProperties",
"properties": {
"java.specification.version": {
"value": "13"
},
"sun.jnu.encoding": {
"value": "UTF-8"
},
"java.class.path": {
"value": "...
....
로깅 레벨 확인 (/loggers)
- 로깅 레벨 수준이 어떻게 설정되어 있는지 확인한다
- GET http://localhost/8080/actuator/loggers
"levels": [
"OFF",
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE"
],
"loggers": {
"ROOT": {
"configuredLevel": "INFO",
"effectiveLevel": "INFO"
},
"SQL dialect": {
"effectiveLevel": "INFO"
},
"_org": {
"effectiveLevel": "INFO"
},
"_org.springframework": {
"effectiveLevel": "INFO"
},
"hello": {
"effectiveLevel": "INFO"
},
"hello.ActuatorApplication": {
"effectiveLevel": "INFO"
},
"hello.controller": {
"configuredLevel": "DEBUG",
"effectiveLevel": "DEBUG"
},
"hello.controller.LogController": {
"effectiveLevel": "DEBUG"
},
}
}
Actuator 커스텀 기능 만들기
개발자의 요구사항에 맞춘 커스텀 기능 설정이 가능하다
- 기존 기능에 기능을 추가
- 새로운 엔드포인트 개발
기존 기능에 기능 추가
- /info 와 같이 application.properties 파일 내에 내용을 추가하기
- 내용이 너무 많아지면 관리 측면에서 좋지 한다
- 별도의 구현체 클래스를 작성해서 내용을 추가하는 방법
- InfoContributor 인터페이스를 사용해서, 클래스를 만든다
- Builder 객체는 액추에이터 패키지의 Info 클래스 안에 정의돼 있는 클래스로서 Info 엔드포인트에서 보여줄 내용을 담는 역할을 수행한다
@Component
public class CustomInfoContributor implements InfoContributor {
@Override
public void contribute(Builder builder) {
Map<String, Object> content = new HashMap<>();
content.put("code-info", "InfoContributor 구현체에서 정의한 정보");
builder.withDetail("custom-info-contributor", content)
}
}
# 결과값
{
"organization":
{
"name": "wikibooks"
},
"contact":
{
"email" : "joon@gmail.com",
"phoneNumber" : "010-1234-1234"
},
"custom-info-contributor" : {
"code-info" : "InfoContributor 구현체에서 정의한 정보"
}
}
커스텀 엔드포인트 생성
- @Endpoint 어노테이션으로 빈에 추가된 객체들은 @ReadOperation, @WriteOperation, @DeleteOperation 어노테이션을 사용해 JMX나 HTTP를 통해 커스텀 엔드포인트를 노출시킬 수 있다
- JMX에서만 사용하거나 HTTP에서만 사용하는 것으로 제한하고 싶으면 @JmxEndpoint, @WebEndpoint 어노테이션을 사용하면 된다
@Component
@Endpoint(id = "example")
public class ExampleEndPoint {
private Map<String, Object> exampleContent = new Map<>();
@ReadOperation
public Map<String, Object> getExample() {
return exampleContent;
}
@WriteOperation
public Map<String, Object> writeExample(String key, Object value) {
exampleContent.put(key, value);
return exampleContent;
}
@DeleteOperation
public Map<String, Object> deleteExample(String key) {
exampleContent.remove(key);
return exampleContent
}
}
- GET http://localhost:8080/actuator/example 을 통해 확인할 수 있다
- 처음에는 아무것도 없는 결과값이 나온다
- POST http://localhost:8080/actuator/example 를 통해 BODY에 key와 value의 데이터를 넣어주면 결과값이 추가가 된다
- DELETE http://localhost:8080/actuator/example 에 key를 넣으면, 해당 key가 존재하면 지워진다
'독서 > 스프링 부트 핵심 가이드' 카테고리의 다른 글
[스프링 부트 핵심 가이드] Chapter 13장. 서비스의 인증과 권한 부여 (0) | 2023.10.14 |
---|---|
[스프링 부트 핵심 가이드] Chapter 12장. 서버 간 통신 (0) | 2023.10.08 |
[스프링 부트 핵심 가이드] Chapter 10장. 유효성 검사와 예외 처리 (0) | 2023.10.01 |
[스프링 부트 핵심 가이드] Chapter 9장. 연관 관계 매핑 (0) | 2023.09.24 |
[스프링 부트 핵심 가이드] Chapter 8장. Spring Data JPA 활용 (1) | 2023.09.16 |