본문 바로가기
독서/스프링 부트 핵심 가이드

[스프링 부트 핵심 가이드] Chapter 11장. 액추에이터 활용하기

by JayAlex07 2023. 10. 8.

스프링 부트 핵심 가이드

img

 

[스프링 부트 핵심 가이드] 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
# 예시
{
    "organization":
    {
        "name": "wikibooks"
    },
    "contact":
    {
        "email" : "joon@gmail.com",
        "phoneNumber" : "010-1234-1234"
    }
}

 

 

어플리케이션 상태 (/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)

# 예시
{
  "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)

  "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
    }
}