전체 보기
🍀

Spring Actuator 이용한 모니터링(+버전 관리), Actuator 의존성 충돌 해결

작성일자
2023/10/11
태그
DIARY_DEVELOP
프로젝트
FIS
책 종류
1 more property
오늘의 글 요약
핵심 : Spring Boot Actuator를 이용해 git 정보를 expose 해주는 방식으로 버전 번호 관리함
gradle-git-properties 플러그인을 이용해 build 시 git.properties 파일을 생성하게 해줌
git.properties 파일 내용을 info endpoint에 넣어줌
장점 : 로컬 개발이 아닌 개발서버, 운영서버에 구동중인 application이 생각과 다르게 동작할때, 이게 어떤 git commit까지 반영된건지, branch가 어떤건지를 actuator 를 통해 확인할 수 있음
이슈 : Spring actuator 의존성 추가 시 [Failed to start bean 'documentationPluginsBootstrapper'] 에러 남
Springfox는 Spring MVC가 Ant-based path matcher를 기본값으로 하여 경로를 찾는 것으로 가정하는데 Spring MVC가 2.6.X부터 기본값을 Ant-based path matcher에서 PathPattern-based matcher로 변경하여서 발생하는 버그였음
WebEndpointServletHandlerMapping 추가해서 해결해줌
결론 : /actuator/info 엔드포인트에서 아래와 같이 commit message 내용으로 버전 확인 가능함
{ "git": { "branch": "master", "commit": { "time": "2023-09-22T08:56:26Z", "message": { "full": "v1.0.0\n", "short": "v1.0.0" }, ... }
JSON
복사

Spring actuator 이용한 애플리케이션 모니터링 (+버전관리)

서론)
이전에 github actions 초록불만 보고서 배포가 잘 되었다고 생각했는데, 알고보니 docker image pull을 실패하고서 계속 과거의 특정 이미지만 배포하고 있었던 적이 있었다.
api 배포서버에 올렸는데 프론트에서 자꾸 없다해서 이상하다,,,싶다가 좀 뒤늦게 잘못된 걸 찾았다.
이런 일을 방지하기 위해선 배포된 플젝의 버전을 확인할 수 있어야 한다. 이번 프로젝트에서 프론트로부터 해당 요청을 받았다.
그럼 배포된 프로젝트가 가장 최신에 배포한 버전으로 제대로 배포되었는지 어떻게 확인할 수 있을까?
1.
build.gradle에 버전을 명시하는 방법이 있을 거고
2.
docker tag를 사용해도 가능하고
3.
github tag를 사용하는 것도 좋다.
다만 2번이나 3번 방식의 단점은,,, docker hub와 github 에 종속적이게 된 단 거다. 우리 팀은 코드단으로 버전을 관리하고 싶었다.
그렇다면, 1번 방식밖에 답이 없는 것일까?
1번 방식의 크리티컬한 단점은 자동화가 불편하단 점이다. cicd를 구축했을 때 코드단의 버전을 바꾸는 커밋을 날리는 시점이 애매하다.
내가 생각한 가장 간단한 방법은 3번이다, 오잉? 3번은 github에 종속적이라 싫다매요. 라고 묻는다면
Spring Actuator를 잘 활용하면 된다고 답하겠다.
그래서 오늘은 Spring Actuator를 이용해 어떻게 버전 관리를 github에 종속적이지 않게 할 수 있는지 그 방법을 적겠다.
본론)
원리
먼저 gradle-git-properties 플러그인을 사용해 build 시 현재 git 정보를 코드 상으로 저장하게 한다.
그리고, spring actuator 의존성을 추가하면 spring boot가 기본으로 제공하는 엔드포인트인 /actuator/info 를 이용해 아래와 같이 git 정보를 확인할 수 있다.
{ "git": { "branch":"master", "commit":{ "time":"2023-09-25T09:03:07Z", "message":{ "full":"v1.1.0\n\nv1.1.0", "short":"v1.1.0"}, ...
JSON
복사
이 프로세스 대로 배포된다면 우린 배포 환경에서도 해당 엔드포인트로 git 정보를 확인해 배포된 버전 정보까지 확인할 수 있을 것이다. 뭐,,, cicd 과정에서 git tag를 달아주는 것도 좋지만 우리팀은 일단 커밋메시지(겸 릴리즈 pr 제목)으로 확인하기로 했다. 추후에 이 커밋 메시지(v1.1.0)으로 깃 태그까지 함께 달아주면 더할 나위 없이 좋을 것이다. 이 부분은 별도의 포스트로 작성하겠다.
적용
build.gradle → 플러그인, 의존성 추가
plugins { ... id "com.gorylenko.gradle-git-properties" version "2.4.1" } dependencies { ... implementation 'org.springframework.boot:spring-boot-starter-actuator' }
JSON
복사
application.yml → actuator 엔드포인트 추가
management: endpoints: web: exposure: include: info info: git: mode: full
JSON
복사
끝입니다,,,ㅋㅋㅋㅋㅋ 자 이제 build 후 실행 해서 localhost:8080/actuator/info 로 들어가보세용 요걸 배포하면 인제 배포환경에서도 해당 엔드포인트를 쓸 수 있는거구요~
결론) spring actuator 정말 편하다! 다들 꼭 써보길 추천한다
참고)
gradle-git-properties 플러그인
gradle-git-properties
n0mer
그 외 배경 지식

Spring actuator 의존성 추가 npe 해결

gradle로 실행할 때만 뜸,,,
cicd 환경은 gradle 로 빌드하기에 일단 해결해주기로 함
이게,,, actuator 의존성이 swagger 의존성이랑 충돌하는 게 특정 버전에서만 생기는 버그라 한다
요 두 녀석이다
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2' implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
Java
복사
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Java
복사
버전을 내리긴 싫어서 아래 코드 추가해줘서 해결했다.
@Configuration @EnableSwagger2 public class SwaggerConfig { // 요 녀석이랑 @Bean public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) { List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>(); Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints(); allEndpoints.addAll(webEndpoints); allEndpoints.addAll(servletEndpointsSupplier.getEndpoints()); allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints()); String basePath = webEndpointProperties.getBasePath(); EndpointMapping endpointMapping = new EndpointMapping(basePath); boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath); return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null); } // 요 녀석 두 개 추가해줬다. private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) { return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT)); } @Bean public Docket restAPI() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Fis-police Spring Boot REST API") .version("1.0.0") .description("swagger api ") .build(); } }
Java
복사