spring / / 2023. 10. 13. 07:21

spring boot actuator 사용하기

1. 개요

actuator는 스프링 부트 애플리케이션의 모니터링이나 메트릭 기능을 HTTP와 JMX의 엔드포인트를 통해 제공한다.

사용하는 방식은 spring-boot-starter-actuator 의존성을 추가하는 것이다.

Maven 프로젝트에서는 아래와 같이 추가할 수 있다.

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

2. Endpoints

기술에 구애받지 않는 공통적인 enpoint

ID Description
auditevents 현재 애플리케이션의 audit event 정보를 노출한다. AuditEventRepositoryBean이 필요하다.
beans 애플리케이션 내의 모든 스프링 빈의 목록을 표시한다.
caches 사용 가능한 캐쉬를 노출한다.
conditions configuration과 자동 구성 클래스, 매칭이 되지않은 이유에 대한 조건을 표시한다.
configprops 모든 @ConfigurationProperties의 목록을 나타낸다.
env 스프링의 ConfigurableEnvironment의 프로퍼티를 노출한다.
flyway 적용되어 있는 Flyway 데이터베이스 마이그레이션을 표시한다. 한 개 이상의 Flyway bean이 필요하다.
health 애플리케이션 health 정보를 표시한다.
httpexchanges HTTP exchange 정보를 나타낸다. (기본적으로 최근 100개의 request-response)
info 애플리케이션의 정보를 나타낸다.
integrationgraph Spring Integration 그래프를 나타낸다. spring-integration-core의 의존성이 필요하다.
loggers 애플리케이션의 로거 구성을 나타내고 수정한다.
liquibase Liquibase 데이터베이스 마이그레이션을 나타낸다. 하나 이상의 Liquibase 빈이 필요하다.
metrics 애플리케이션의 metric 정보를 나타낸다.
mappings 모든 @RequestMapping path 정보를 나타낸다.
quartz Quartz 스케쥴러 잡 정보를 나타낸다.
scheduledtasks 애플리케이션의 스케쥴 작업을 나타낸다.
sessions 스프링 세션 저장소의 사용자 세션 조회 및 삭제를 할 수 있게 한다. Spring Session을 사용하는 서블릿 기반 웹 애플리케이션이 필요하다.
shutdown 애플리케이션을 gracefully shutdown을 하게 한다. jar 패키징을 사용할 때만 동작한다. 기본값: false
startup 애플리케이션 시작 시 수집되는 데이터를 표시한다. SpringApplication이 BufferingApplicationStartup으로 구성되어야 한다.
threaddump 쓰레드 덤프를 수행한다.

웹 애플리케이션(Spring MVC, Spring WebFlux, Jersey)을 사용하면 다음 endpoint를 사용할 수 있다.

ID Description
heapdump 힙 덤프파일을 만든다. HotSpot JVM에서는 HPROF 파일 포맷이 생성이 되고 OpenJ9에서는 PHD 포맷이 생성이 된다.
logfile 로그 파일 내용을 리턴한다 (logging.file.name 혹은 logging.file.path 값이 설정되어 있는 경우)

endpoint path 커스트마이징

/actuator 경로를 변경하려면

base-path에 변경할 경로를 입력하면 된다.

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

http://localhost:8080/actuator으로 접속되지 않고 http://localhost:8080/manage 로 접속이 가능하다.

endpoint의 경로를 변경하려면

path-mapping에 변경할 enpoint와 변경할 이름을 적으면 된다.

아래 예제는 beansspringbeans로 변경한 것이다.

management:
  endpoints:
    web:
      path-mapping:
        beans: springbeans

http://localhost:8080/actuator/beans 대신 http://localhost:8080/actuator/springbeans로 접속이 된다.

포트 정보를 변경하려면

actuator를 다른 포트로 사용하려면 아래에 포트정보를 입력하면 된다.

management:
  server:
    port: 8081

http://localhost:8080/actuator 대신 http://localhost:8081/actuator으로 접속이 된다.

3. 주요 endpoint

beans

url
http://localhost:8080/actuator/beans
설명

BeanFactory의 모든 빈을 표시한다. 필터링 기능을 제공하지 않는다.

health

url

http://localhost:8080/actuator/health

설명
  • 운영 중인 애플리케이션의 상태 체크를 위해 health 정보를 사용할 수 있다. 때로는 운영 중인 시스템이 다운되었을 때 알림용도로 사용되기도 한다.
  • 의존성에 HealthIndicator를 구현한 구현체가 있다면 동작을 한다.
    • db, diskspace, elasticsearch, hazelcast 등이 있다.
  • RoutingDataSourceHealthContributor는 여러 DataSource의 헬스를 체크하는데 여러 개 중 하나의 DataSource만 문제가 발생하더라도 서비스 다운으로 표시한다.
Name Description
never 상세정보를 나타내지 않는다.
when-authorized 상세정보는 권한있는 사용자에게만 표시한다. 역할이 management.endpoint.health.roles을 통해서 구성될 수 있다.
always 상세정보가 모든 사용자에게 표시된다.
  • 기본값은 never이다.
  • 사용자는 하나 이상의 역할에 포함되어 있을 때 권한이 있다고 판단된다.
  • 구성된 역할이 없다면 모든 인증된 사용자는 접근된다. (기본값)
  • 역할은 management.endpoint.health.roles 속성을 통해 구성할 수 있다.

[never]

{
  "status": "UP"
}

[always]

{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "H2",
        "validationQuery": "isValid()"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 494384795648,
        "free": 258507841536,
        "threshold": 10485760,
        "exists": true
      }
    },
    "ping": {
      "status": "UP"
    }
  }
}
커스텀 HealthIndicator 생성

HealthIndicator를 구현한 스프링 빈을 등록하여 커스텀 HealthIndicator을 만들 수 있다.

@Component
public class CustomHealthIndicator 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 0;
    }
}

이렇게 구현하면 http://localhost:8080/actuator/health 응답값에 custom이 포함되는 것을 확인할 수 있다.

{
  "status": "UP",
  "components": {
    "custom": {
      "status": "UP"
    },
    ...
}

conditions

url

http://localhost:8080/actuator/conditions

설명

스프링 부트의 자동구성과 개발자가 직접 구성한 빈의 평가된 조건에 대한 정보

  • positiveMatches: 매칭된 조건의 클래스와 메소드
  • negativeMatches: 매칭되지 않은 조건의 클래스와 메소드
{
  "contexts" : {
    "application" : {
      "positiveMatches" : {
        "EndpointAutoConfiguration#endpointOperationParameterMapper" : [ {
          "condition" : "OnBeanCondition",
          "message" : "@ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper; SearchStrategy: all) did not find any beans"
        } ],
        ...
      },
      "negativeMatches" : {
        "WebFluxEndpointManagementContextConfiguration" : {
          "notMatched" : [ {
            "condition" : "OnWebApplicationCondition",
            "message" : "not a reactive web application"
          } ],
          "matched" : [ {
            "condition" : "OnClassCondition",
            "message" : "@ConditionalOnClass found required classes 'org.springframework.web.reactive.DispatcherHandler', 'org.springframework.http.server.reactive.HttpHandler'"
          } ]
        },
        ...
      },
      "unconditionalClasses" : [ "org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration", "org.springframework.boot.actuate.autoconfigure.endpoint.jackson.JacksonEndpointAutoConfiguration", "org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration" ]
    }
  }
}

configprops

url

http://localhost:8080/actuator/configprops

설명

configprops endpoint는 @ConfigurationProperties 빈에 대한 정보를 제공한다.

{
  "contexts" : {
    "application" : {
      "beans" : {
        "management.endpoints.web.cors-org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties" : {
          "prefix" : "management.endpoints.web.cors",
          "properties" : {
            "allowedOrigins" : [ ],
            "maxAge" : "PT30M",
            "exposedHeaders" : [ ],
            "allowedOriginPatterns" : [ ],
            "allowedHeaders" : [ ],
            "allowedMethods" : [ ]
          },
          "inputs" : {
            "allowedOrigins" : [ ],
            "maxAge" : { },
            "exposedHeaders" : [ ],
            "allowedOriginPatterns" : [ ],
            "allowedHeaders" : [ ],
            "allowedMethods" : [ ]
          }
        },
        ...
      }
    }
  }
}
prefix로 @ConfigurationProperties 빈 조회하기

특정 prefix를 가진 빈을 조회하려면, http://localhost:8080/actuator/configprops/{prefix}로 조회하면 된다.

예) http://localhost:8080/actuator/configprops/spring.transaction

env

url

http://localhost:8080/actuator/env

설명

애플리케이션의 전체 환경정보를 조회한다.

{
  "activeProfiles" : [ ],
  "propertySources" : [ {
    "name" : "servletContextInitParams",
    "properties" : { }
  }, {
    "name" : "systemProperties",
    "properties" : {
      "java.specification.version" : {
        "value" : "17"
      },
      "java.class.path" : {
        "value" : "/root/.gradle/caches/7.6.2/workerMain/gradle-worker.jar:.............."
      },
      "java.vm.vendor" : {
        "value" : "BellSoft"
      }
    }
  }, {
    "name" : "systemEnvironment",
    "properties" : {
      "JAVA_HOME" : {
        "value" : "/opt/openjdk",
        "origin" : "System Environment Property \"JAVA_HOME\""
      }
    }
  }, {
    "name" : "Config resource 'class path resource [application.properties]' via location 'classpath:/'",
    "properties" : {
      "com.example.cache.max-size" : {
        "value" : "1000",
        "origin" : "class path resource [application.properties] - 1:29"
      }
    }
  } ]
}
단일 속성 조회

단일 속성을 조회하려면 http://localhost:8080/actuator/env/{property.name} 으로 조회하면 된다.

예) http://localhost:8080/actuator/env/java.specification.version

caches

url

http://localhost:8080/actuator/caches

설명

애플리케이션의 캐시정보를 표시한다.

응답값

{
  "cacheManagers" : {
    "anotherCacheManager" : {
      "caches" : {
        "countries" : {
          "target" : "java.util.concurrent.ConcurrentHashMap"
        }
      }
    },
    "cacheManager" : {
      "caches" : {
        "cities" : {
          "target" : "java.util.concurrent.ConcurrentHashMap"
        },
        "countries" : {
          "target" : "java.util.concurrent.ConcurrentHashMap"
        }
      }
    }
  }
}
캐쉬 이름으로 조회하기

캐쉬 이름으로 조회하기 위해서 /actuator/caches/{name}으로 요청을 하면 된다.

예) http://localhost:8080/actuator/caches/cities

응답값

{
  "target" : "java.util.concurrent.ConcurrentHashMap",
  "name" : "cities",
  "cacheManager" : "cacheManager"
}
모든 캐쉬 evict하기
$ curl 'http://localhost:8080/actuator/caches' -i -X DELETE
캐쉬 이름으로 evict하기
$ curl 'http://localhost:8080/actuator/caches/countries?cacheManager=anotherCacheManager' -i -X DELETE \
    -H 'Content-Type: application/x-www-form-urlencoded'

info

url

http://localhost:8080/actuator/info

설명
자동 구성 InfoContributors

스프링에서 자동으로 구성해주는 InfoContributors 빈이다.

ID Name Description Prerequisites
build BuildInfoContributor 빌드 정보 A META-INF/build-info.properties resource.
env EnvironmentInfoContributor info로 시작하는 이름의 Environment의 속성을 노출 None.
git GitInfoContributor git 정보를 노출 A git.properties resource.
java JavaInfoContributor Java Runtime 정보 노출 None.
os OsInfoContributor 운영 체제 정보 노출 None.
  • management.info.<id>.enabled 프로퍼티 속성으로 활성화할 수 있다.
커스텀 애플리케이션 정보

application.yml에 info.*로 설정함으로써 info 엔드포인트에 정보를 노출하게 할 수 있다.

info:
  app:
    name: rudaks-app

이렇게 설정하면 아래와 같이 info의 응답결과에 포함되는 것을 알 수 있다.

{
  "app": {
    "name": "rudaks-app",
    ...
  }

하드코딩된 값을 사용하지 않고 build time에 info 정보를 포함할 수 있다.

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

Git Commit 정보

GitProperties 빈은 git.properties 파일이 클래스 패스 루트에 있다면 자동으로 구성이 된다.

git.properties를 자동생성하는 방법은 아래 플러그인을 추가하면 빌드 시 git.properties를 생성한다.

maven에서는 아래를 추가하면 된다.

<build>
 <plugins>
     <plugin>
         <groupId>io.github.git-commit-id</groupId>
         <artifactId>git-commit-id-maven-plugin</artifactId>
     </plugin>
 </plugins>
</build>

  • 기본적으로 git.branch, git.commit.id, git.commit.time을 노출한다.
management:
  info:
    git:
      mode: "full" # simple/full
build 정보

클래스 패스에 META-INF/build-info.properties 파일이 있다면 표시한다.

maven에서 build정보를 생성하려면 아래와 같이 info-info goal을 실행하면 된다.

<build>
 <plugins>
     <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
         <version>3.0.5</version>
         <executions>
             <execution>
                 <goals>
                     <goal>build-info</goal>
                 </goals>
             </execution>
         </executions>
     </plugin>
 </plugins>
</build>

다시 실행해보면 아래와 같이 표시된다.

{
  ...
  "build": {
    "artifact": "spring-boot-actuator-sample",
    "name": "spring-boot-actuator-sample",
    "time": "2023-10-11T23:05:44.860Z",
    "version": "0.0.1-SNAPSHOT",
    "group": "com.example"
  },
  ...
}

loggers

url

http://localhost:8080/actuator/loggers

설명

애플리케이션에 설정된 logger와 레벨 구성을 확인할 수 있다.

{
  "levels" : [ "OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" ],
  "loggers" : {
    "ROOT" : {
      "configuredLevel" : "INFO",
      "effectiveLevel" : "INFO"
    },
    "com.example" : {
      "configuredLevel" : "DEBUG",
      "effectiveLevel" : "DEBUG"
    }
  },
  "groups" : {
    "test" : {
      "configuredLevel" : "INFO",
      "members" : [ "test.member1", "test.member2" ]
    },
    "web" : {
      "members" : [ "org.springframework.core.codec", "org.springframework.http", "org.springframework.web", "org.springframework.boot.actuate.endpoint.web", "org.springframework.boot.web.servlet.ServletContextInitializerBeans" ]
    },
    "sql" : {
      "members" : [ "org.springframework.jdbc.core", "org.hibernate.SQL", "org.jooq.tools.LoggerListener" ]
    }
  }
}
단일 logger 조회하기

단일 logger를 조회하기 위해서는 /actuator/loggers/{logger.name}를 조회하면 된다.

예) http://localhost:8080/actuator/loggers/com.example

응답값

Path Type Description
configuredLevel String logger의 설정된 레벨이 있다면 표시한다. 없으면 null
effectiveLevel String logger가 설정되어 있으면 그 값을 반환하고 없다면 상위수준으로 검색한 다음 적용된 레벨을 표시한다.
로그 레벨 변경하기

logger의 레벨을 변경하기 위해 /actuator/loggers/{logger.name}으로 POST 요청을 하면 된다.

$ curl 'http://localhost:8080/actuator/loggers/com.example' -i -X POST \
    -H 'Content-Type: application/json' \
    -d '{"configuredLevel":"debug"}'

요청값

Path Type Description
configuredLevel String logger의 레벨. 레벨을 초기화하라면 제외하면 된다.
로그 레벨 초기화하기
$ curl 'http://localhost:8080/actuator/loggers/com.example' -i -X POST \
    -H 'Content-Type: application/json' \
    -d '{}'

logger의 레벨을 초기화하기 위해 /actuator/loggers/{logger.name}으로 빈 값으로 POST 요청을 하면 된다.

httptrace

url

http://localhost:8080/actuator/httptrace

설명

HTTP 요청-응답에 대한 정보를 표시한다.

활성화하기 위해서 HttpTraceRepository의 구현체를 빈으로 등록해줘야 한다. 여기서는 InMemoryHttpTraceRepository를 사용한다.

@Bean
public HttpTraceRepository createTraceRepository() {
    return new InMemoryHttpTraceRepository();
}

응답값

{
  "exchanges" : [ {
    "timestamp" : "2022-12-22T13:43:41Z",
    "request" : {
      "uri" : "https://api.example.com",
      "method" : "GET",
      "headers" : {
        "Accept" : [ "application/json" ]
      }
    },
    "response" : {
      "status" : 200,
      "headers" : {
        "Content-Type" : [ "application/json" ]
      }
    },
    "principal" : {
      "name" : "alice"
    },
    "session" : {
      "id" : "52f5e16e-b804-4d9b-a02a-c556b70a2deb"
    },
    "timeTaken" : "PT0.023S"
  } ]
}

스프링 3.0에서는 HttpTraceRepository의 이름이 HttpExchangeRepository으로 변경이 되었다.
호출하는 endpoint도 /actuator/httptrace에서 /actuator/httpexchanges으로 변경되었다.

scheduledtasks

url

http://localhost:8080/actuator/scheduledtasks

설명

애플리케이션의 스케쥴 작업에 대한 정보를 제공한다.

/actuator/scheduledtasks으로 요청을 하면 아래와 같이 표시된다.

{
  "cron": [

  ],
  "fixedDelay": [

  ],
  "fixedRate": [
    {
      "runnable": {
        "target": "com.example.actuator.scheduled.ScheduleBean.fixedRateJob"
      },
      "initialDelay": 0,
      "interval": 1000
    }
  ],
  "custom": [

  ]
}

mappings

url

http://localhost:8080/actuator/mappings

설명

애플리케이션의 request mapping에 대한 정보를 제공한다.

응답값

{
  "contexts" : {
    "application" : {
      "mappings" : {
        "dispatcherServlets" : {
          "dispatcherServlet" : [ {
            "handler" : "Actuator web endpoint 'mappings'",
            "predicate" : "{GET [/actuator/mappings], produces [application/vnd.spring-boot.actuator.v3+json || application/vnd.spring-boot.actuator.v2+json || application/json]}",
            "details" : {
              "handlerMethod" : {
                "className" : "org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping.OperationHandler",
                "name" : "handle",
                "descriptor" : "(Ljakarta/servlet/http/HttpServletRequest;Ljava/util/Map;)Ljava/lang/Object;"
              },
              "requestMappingConditions" : {
                "consumes" : [ ],
                "headers" : [ ],
                "methods" : [ "GET" ],
                "params" : [ ],
                "patterns" : [ "/actuator/mappings" ],
                "produces" : [ {
                  "mediaType" : "application/vnd.spring-boot.actuator.v3+json",
                  "negated" : false
                }, {
                  "mediaType" : "application/vnd.spring-boot.actuator.v2+json",
                  "negated" : false
                }, {
                  "mediaType" : "application/json",
                  "negated" : false
                } ]
              }
            }
          }, 
        ...
    }
  }
}

startup

url

http://localhost:8080/actuator/startup

설명

애플리케이션의 시작 과정 기록된 단계를 조회하기 위해 사용한다.

{
  "springBootVersion" : "3.1.4",
  "timeline" : {
    "startTime" : "2023-09-21T10:29:31.057906113Z",
    "events" : [ {
      "endTime" : "2023-09-21T10:29:31.162405607Z",
      "duration" : "PT0.000005249S",
      "startTime" : "2023-09-21T10:29:31.162400358Z",
      "startupStep" : {
        "name" : "spring.beans.instantiate",
        "id" : 3,
        "tags" : [ {
          "key" : "beanName",
          "value" : "homeController"
        } ],
        "parentId" : 2
      }
    }, {
      "endTime" : "2023-09-21T10:29:31.162418344Z",
      "duration" : "PT0.000027345S",
      "startTime" : "2023-09-21T10:29:31.162390999Z",
      "startupStep" : {
        "name" : "spring.boot.application.starting",
        "id" : 2,
        "tags" : [ {
          "key" : "mainApplicationClass",
          "value" : "com.example.startup.StartupApplication"
        } ]
      }
    } ]
  }
}

startup을 사용하기 위해서 SpringBootApplication을 BufferingApplicationStartup으로 변경해야 한다.

public static void main(String[] args) {
     //        SpringApplication.run(ActuatorApplication.class, args);
 SpringApplication app = new SpringApplication(ActuatorApplication.class);
 app.setApplicationStartup(new BufferingApplicationStartup(2048));
 app.run(args);
}

참고

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html

https://docs.spring.io/spring-boot/docs/current/actuator-api/htmlsingle/

http://forward.nhnent.com/hands-on-labs/java.spring-boot-actuator/04-endpoint.html

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유