spring boot/actuator in spring boot

spring boot 3.x + actuator 파헤치기. 6. about info endpoint

Hello World Study 2023. 4. 1. 11:53

https://youtu.be/OxXLOLVkXnU

 

이번시간에는 info endpoint 에 대해 알아보겠습니다.

 

actuator 자체가 주로 정보를 제공하는 기능이라서 info endpoint 라는 이름이 와닿지 않습니다.

 

기본 제공 info endpoint

이름 그대로 정보성 endpoint 인데, spring boot 에서는 아래 5가지를 기본 제공해주고 있습니다.

각 항목이 어떤 정보를 보여주는지는 차차 알아보기로 하고, 우선 prerequisites 즉 선결조건이 있는게 build 와 git 입니다. 선결조건인 info.properties 나 git.properties 파일이 없다면 disable 된다고 봐야 하며, 나머지 3가지는 기본이 disable 되어 있습니다. 결국 별도 설정을 하지 않으면 info endpoint 는 아무런 값을 보여주지 않습니다. 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.info.auto-configured-info-contributors

application.yml 에 아래처럼 web endpoint 만 모두 열어두고 spring boot 구동해봅시다.

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

아래처럼 /actuator 에 info 항목이 보이긴 하지만, 막상 해당 endpoint 로 들어가면 비어있는 json 만 응답되는걸 알 수 있습니다.

아래처럼 application.yml 내에 management.info 아래에 각 항목별로 enable, disable 을 설정할 수 있습니다.

위에서 설명했듯이 build, git 은 enable 되어 있고 나머지는 disable 이 기본 값인걸 알 수 있습니다. 즉 별도 설정을 하지 않으면 해당 디폴트값으로 동작을 합니다.

아래처럼 management.info 하위에 os, java, env 에 대해 enabled: true 로 설정을 해주고 spring boot 를 재구동하겠습니다. 

management:
  endpoints:
    web:
      exposure:
        include: "*"
  info:
    os:
      enabled: true
    java:
      enabled: true
    env:
      enabled: true

아래처럼 이제는  java 와 os 정보가 상세히 나옵니다.

info endpoint 내의 env 설정

그런데 env 는 왜 보이지 않을까요? 

아래처럼 info. 으로 시작하는 환경변수를 노출해준다고 가이드에 적혀있습니다.

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.info.auto-configured-info-contributors

아래처럼 application.yml 파일에 key: value 형태로 값을 적어주면 spring 에서는 환경변수로 인식을 합니다.

따라서 기존 application.yml 에 아래 내용을 추가로 넣어보겠습니다.  

 

info:
  my-app:
    any-value: someValue
    group-id: "@project.groupId@"
    artifact-id: "@project.artifactId@"
    encoding: "@project.build.sourceEncoding@"
    java:
      version: "@java.version@"
  made-by: developerY

@xxx.xxx@ 와 같이 특이한 형태가 있는데, 이건 maven 의 properties 에 해당하는 값을 읽어올때 사용하는 특수 문법 정도로 생각하면 됩니다. ( gradle 의 경우 ${xxx.xxx} 와 같은 형식입니다. )

아래는 현재 pom.xml 의 일부 내용인데 <java.version> 에 17이 들어가 있으며, groupId 와 artifactId 에 특정 값이 들어가 있습니다. 이런식으로 pom.xml 의 내용을 actuator info endpoint 에 노출시키고 싶으면 @xxx.xxx@ 와 같이 적어주면 됩니다.

	<groupId>me.developery</groupId>                    <--- 
	<artifactId>actuator-study</artifactId>             <--- 
	<version>0.0.1-SNAPSHOT</version>
	<name>actuator-study</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>                 <--- 
	</properties>

실행결과는 아래와 같습니다. 기존 java 와 os 가 보이고, 추가적으로 application.yml 의 info 하위에 적은 my-app 과 made-by 가 보입니다. env 라는 필드 하위에 my-app, made-by 가 들어가는게 아니니 주의하세요.

 

@xx.xx@ 형식은 actuator 전용이 아닙니다. 그래서  build time 에 maven 이나 gradle 의 속성값을  application.yml 에 넣어줄 수 있습니다. application.yml에 넣어주면 환경변수로 인식이 되므로 결국, maven , gradle 속성값을 환경변수로 사용할 수있다는 뜻입니다.

 

build 툴인 maven 과 gradle 에 따라 설정이 다르므로, 각각의 상세한 예시와 설명은 아래 공식 가이드를 참고해주세요.

https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.properties-and-configuration.expand-properties.maven

https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.properties-and-configuration.expand-properties.gradle

 

env endpoint ( /actuator/env   VS  /actuator/info )

조심할 부분은 아래처럼 actuator 에 env 라는 endpoint 가 제공되고 있으며, 여기에는 Environment 클래스(=환경변수 저장 클래스)내의 정보 즉 모든 환경변수값을 노출해 주고 있습니다.

따라서 아래처럼 /actuator/env 에 들어가면 info. 로 시작하는 환경변수도 보여집니다.

즉 info. 로 시작하는 환경변수는 /actuator/env 에도 보여지며, /actuator/info 에도 보여집니다.

 

이왕 /actuator/env 를 살펴봤으니 조금 더 살펴봅시다. 내용을 보면 **** 와 같이 실제로 필요한 value 부분이 안보이도록 되어 있습니다. 민감정보이니 디폴트가 hidden 인것같습니다. application.yml 에 env endpoint 에 대한 설정을 살펴봅시다.

개별 endpoint 설정은 management.endpoint. 하위에서 설정을 합니다.

그래서 아래처럼 management.endpoint.env. 로 들어가면 show-values 라는 필드가 보이며 이를 ALWAYS 로 설정해주고 spring boot 를 재구동해봅시다.

다른 endpoint 들은 enabled 정도의 필드만 보이는데 env 는 기본적으로 value 값을 **** 식으로 보여주기에 show-values 필드가 추가로 제공됩니다.

이제 다시 /actuator/env 로 들어가면 모든 값들이 **** 가 아니라 실제 값이 다 보이는걸 알 수 있습니다. 

 

git info 

이제 spring boot 가 자동구성으로 제공하는 info 정보중 git info 에 대해 알아보겠습니다. 앞서 본것처럼 prerequisites 즉 선결조건이 있습니다. git.properties 파일이 있어야 하는것이죠.

아래 영상처럼 공식 가이드에 따라 pom.xml 에 plugin 을 적어주고, maven clean, install 을 해주면 target 디렉토리내에 git.properties 파일이 생성됩니다. 이제부터는 info endpoint 에 git 정보가 함께 보이는걸 알 수있습니다.

plugin 이 git.properties 파일을 빌드시 생성해주는 역할을 합니다. plugin 이 동작하기 위해 maven install  혹은 maven package 와 같은 명령을 수행해서 빌드가 되도록 해줬습니다.

위 설정에 사용된 링크와 실제 값은 아래와 같습니다.

 

플러그인 설정:

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

https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.build.generate-git-info

 

git.properties 에는 내용이 많은데 actuator 에는 별로 보이지 않습니다. 뭔가 설정이 필요하겠죠?

아래처럼 git설정을 보니 mode 가 있고 기본값이 simple 로 되어 있습니다. full 로 설정한 후 다시 info endpoint 를 확인해보면 git 관련 상세정보가 보이는걸 알 수있습니다. 이렇듯 뭔가 보여지는 값이 부족하다 싶으면 application.yml 에 해당 설정을 찾아보면 됩니다.  ( 물론 공식가이드에도 적혀있습니다.)

git 정보 설정:

management:
  info:
    git:
      mode: "full"

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.info.git-commit-information

 

 

 

 

로컬 개발이 아닌 개발서버, 운영서버에 구동중인 application이 생각과 다르게 동작할때, 이게 어떤 git commit까지 반영된건지, branch가 어떤건지를  actuator 를 통해 확인할 수 있으므로 운영에 좋은 정보로 보입니다. git commit id 까지 보이기에 상당한 민감정보로 생각할 수 있는데 security 와 유사한걸 적용하면 문제 없어보입니다.

 

build info

spring boot가 기본 제공하는 info endpoint 중에 이제 마지막으로 build info 를 살펴보겠습니다. 이전 git info 와 상당히 유사합니다.

아래처럼 pom.xml 에 plugin 을 적어주면 됩니다.

조심할 것은 공식가이드는 항상 최신 버전을 기준으로 가이드 됩니다.

( 특정 버전의 공식 가이드는 아래처럼 current 부분을 3.0.4 와 같이 버전을 명시하면 됩니다. e.g.  https://docs.spring.io/spring-boot/docs/3.0.4/reference/html/howto.html#howto.build.generate-info )

그래서 제가 이 프로젝트 생성시에는 3.0.4 였으나 현재는 3.0.5 가 최신입니다. 그래서 공식 가이드에는 플러그인 버전이 3.0.5 로 적혀있습니다. 이걸 그대로 복붙하면 에러가 나거나 오류가 날 수 있습니다. 보통 spring boot 에서는 많은 라이브러리, 플러그인에 대해 잘 적용되는 버전을 미리 지정해두었습니다. 아래 영상처럼 parent 를 따라 가다보면 우리가 방금 넣은 plugin 버전이 명시되어 있습니다. 따라서 version을 적지 않는게 더 좋습니다. 

 

 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.info.build-information

https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.build.generate-info

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>3.0.4</version>    <-- 자신의 spring boot 버전에 맞게 설정 필요. spring-boot-starter-parent 에 의해 version을 상속받기에 version을 적지 않는걸 권장
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

이 후 maven install 등을 수행하면 META-INF 디렉토리 밑에 build-info.properties 가 생성된걸 알 수 있습니다.

이제 아래처럼 build 필드가 보입니다.

주의할것은 git info 내에도 build 필드가 있다는 겁니다. 서로 보여주는 정보가 약간씩 다르니 주의하세요.

 

custom info endpoint

spring boot 에서 제공하는 위 5 가지 endpoint는 어떻게 구현해서 만들어진걸까요? 우리가 유사하게 info endpoint 를 추가해보면 알 수있습니다. 

아래처럼 InfoContributor 인터페이스를 구현한걸 bean 으로 등록하면 된다고 가이드 되고 있습니다. 

https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.info.writing-custom-info-contributors

우선 앞서 살펴본 git 정보 제공 클래스가 어떻게 만들어졌는지 살펴봅시다.

git info endpoint 도 결국 InfoContirbutor 인터페이스를 구현할 것이니 아래처럼 찾아가 보면 됩니다.

 

가장 중요한 contribute 메서드부분을 보면 아래처럼 

builder.withDetail 메서드에 string 타입의 이름, Map 타입으로 value 를 넣어주고 있습니다.

@Override
public void contribute(Info.Builder builder) {
	builder.withDetail("git", generateContent());  <-- String, Map 타입을 넣었음.
}

 

이제 우리가 직접 info contributor 를 만들어봅시다.

단순 테스트이므로 map 에 하드코딩으로 key1, key2 와 같이 넣었는데, 실제 업무에서는 다른 bean을 참조하여 필요한 정보를 가져온 후 map 에 넣어주면 됩니다. bean으로 등록되어야 하므로 @Component 도 적어줍시다.

@Component
public class MyCustomInfoContributor implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        HashMap<String, String> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");

        builder.withDetail("myCustomInfo", map);
    }
}

아래처럼 위에서 적은 값들이 잘 나오는걸 알 수 있습니다.

 

동작 방식

spring boot 는 InfoContributor 를 구현한 클래스들을 어떻게 찾아서 info endpoint 호출시 정보들을 보여줄까요?

아래처럼 contibute() 메서드를 호출하는 곳을 찾아가보면 InfoEndpoint 라는 클래스인걸 알 수 있습니다.

아래처럼 생성자에서 InfoContributor 를 구현한 bean들을 주입받고,

실제 제공해야할 시점에 for loop 로 bean들의 contribute() 메서드를 호출해서 info 정보를 구성해주고 있습니다.

@Endpoint(id = "info")
public class InfoEndpoint {

	private final List<InfoContributor> infoContributors;

	public InfoEndpoint(List<InfoContributor> infoContributors) {  <-- 생성자로 다른 bean 주입
		Assert.notNull(infoContributors, "Info contributors must not be null");
		this.infoContributors = infoContributors;
	}

	@ReadOperation
	public Map<String, Object> info() {
		Info.Builder builder = new Info.Builder();
		for (InfoContributor contributor : this.infoContributors) {  <-- 등록된 bean들을 loop
			contributor.contribute(builder);
		}
		return OperationResponseBody.of(builder.build().getDetails());
	}

}

spring 에 대해 어느정도 알고 있는 사람이라면 위 방식이 특별해 보일건 없어보입니다. 

 

그리고 spring boot가 기본 제공하는 5가지 endpoint 는 어느 클래스에서 bean으로 등록해주는지 궁금하다면 아래처럼 info 와 autoconfig 를 넣어서 클래스 검색해보면 쉽게 찾을수 있으며, 그곳에 5가지 InfoContributor 를 bean 으로 등록해 주는 코드가 있는걸 알 수 있습니다. 이런식으로 궁금한 코드를 찾아가면서 실력향상에 많은 도움이 됩니다.

 

이번에 다룬 info endpoint 에 대한 소스코드는 아래 링크에 있습니다.

https://github.com/ChunGeun-Yu/spring-actuator-study/tree/infoEndpoint

 

 

많은 도움이 되었길 바랍니다. :)

 


다음 포스팅에서는 가장 유용한 actuator 중의 하나인 metric endpoint 에 대해 알아보겠습니다. 

가장 중요한 metric 인데 여기서 멈추는건 아니죠?