Jira를 모니터링하기 위해 사용자 지정 액추에이터 끝점을 만드는 방법

Spring Boot Actuator는 애플리케이션을 모니터링하기 위한 일련의 엔드포인트를 제공하지만 때로는 특정 메트릭을 얻기 위해 사용자 정의 엔드포인트를 생성해야 할 수도 있습니다.

사용자 지정 끝점을 수행하는 방법에는 두 가지가 있습니다.
  • @Endpoint가 있는 사용자 정의 엔드포인트,
  • @RestControllerEndpoint가 있는 컨트롤러 끝점,
    우리는 두 번째 것만 볼 것입니다.

  • 이 예제에서는 애플리케이션에 대한 사용자 지정 엔드포인트를 생성하지 않고 외부에서 호스팅되는 Jira 서버를 모니터링합니다. 실제로 우리는 그것이 업인지 다운인지 그리고 응답을 반환하는 데 걸리는 시간을 알아야 합니다.

    다음 의존성이 필요합니다.

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-actuator'
        implementation "org.springframework.boot:spring-boot-starter-web"
        implementation "org.springframework.boot:spring-boot-starter-security"
        implementation 'org.springframework.boot:spring-boot-starter-tomcat'
        implementation group: 'com.konghq', name: 'unirest-java', version: '3.11.06'
        implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.11.3'
        implementation 'org.springframework.boot:spring-boot-starter-validation'
        implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.5.0'
        implementation group: 'org.springdoc', name: 'springdoc-openapi-data-rest', version: '1.5.0'
        }
    


    여기 액추에이터 및 jira 서버 연결 속성이 있는 application.yml 파일이 있습니다.

    management:
      endpoints:
        web:
          exposure:
              include: '*'
          base-path: "/management"
      security:
        enabled: false
    
      endpoint:
        health:
          show-details: always
    
    app:
      config:
        jira:
          host: "https://myjiraserver"
          user: "jiraUser"
          password: "jirapwd"
          api-path: "/rest/api/2"
    


    Jira 속성을 Java 구성 클래스와 매핑했습니다.

    @Component
    @ConfigurationProperties("app.config.jira")
    @Validated
    public class JiraConfig {
    
        @NotEmpty
        protected String host;
        @NotEmpty
        protected String user;
        @NotEmpty
        protected String password;
        @NotEmpty
        protected String apiPath;
    
    
        public String getHost() {
            return host;
        }
    
        public void setHost(String host) {
            this.host = host;
        }
    
        public String getUser() {
            return user;
        }
    
        public void setUser(String user) {
            this.user = user;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getApiPath() {
            return apiPath;
        }
    
        public void setApiPath(String apiPath) {
            this.apiPath = apiPath;
        }
    }
    


    다음은 jira 엔드포인트를 호출하고 응답 시간을 제공하는 서비스입니다.

    @Service
    public class JiraConnectorService {
    
        private static final Logger logger = LoggerFactory.getLogger(JiraConnectorService.class);
        public static final String HEADER_ACCEPT = "accept";
        public static final String HEADER_APP_JSON = "application/json";
        public static final String JIRA_MYSELF_ENDPOINT = "/myself";
    
        private JiraConfig jiraConfig;
    
        @Autowired
        public void setJiraConfig(JiraConfig jiraConfig) {
            this.jiraConfig = jiraConfig;
        }
    
        public ResponseTimeData getResponseTime() throws UnirestException {
            logger.info("Get responseTime info");
            String mySelfEndPointUrl = jiraConfig.getHost() + jiraConfig.getApiPath() + JIRA_MYSELF_ENDPOINT;
    
            logger.info("Call {}", mySelfEndPointUrl);
            ResponseTimeData data = new ResponseTimeData();
            long start = System.currentTimeMillis();
    
            HttpResponse<JsonNode> jsonResponse = Unirest.get(mySelfEndPointUrl)
                    .basicAuth(jiraConfig.getUser(), jiraConfig.getPassword())
                    .header(HEADER_ACCEPT, HEADER_APP_JSON)
                    .asJson();
    
            data.setTime(System.currentTimeMillis() - start);
            data.setHttpStatusCode(jsonResponse.getStatus());
            data.setMessage(jsonResponse.getStatusText());
    
            logger.info("Call {} successfull", mySelfEndPointUrl);
            return data;
        }
    }
    


    데이터 모델

    public class ResponseTimeData {
    
        private long time;
        private int httpStatusCode;
        private String message;
    
    
        public long getTime() {
            return time;
        }
    
        public void setTime(long time) {
            this.time = time;
        }
    
        public int getHttpStatusCode() {
            return httpStatusCode;
        }
    
        public void setHttpStatusCode(int httpStatusCode) {
            this.httpStatusCode = httpStatusCode;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    



    public class HealthDtl {
    
        protected String status;
        private int httpStatusCode;
        private String message;
        private Long responseTimeMs;
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    
        public int getHttpStatusCode() {
            return httpStatusCode;
        }
    
        public void setHttpStatusCode(int httpStatusCode) {
            this.httpStatusCode = httpStatusCode;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        public Long getResponseTimeMs() {
            return responseTimeMs;
        }
    
        public void setResponseTimeMs(Long responseTimeMs) {
            this.responseTimeMs = responseTimeMs;
        }
    }
    


    이제 사용자 지정 나머지 끝점 !

    @Component
    @RestControllerEndpoint(id = "jira")
    public class RestJiraEndPoint {
    
        private static final Logger logger = LoggerFactory.getLogger(RestJiraEndPoint.class);
    
        private final JiraConnectorService jiraConnectorService;
    
        public RestJiraEndPoint(JiraConnectorService jiraConnectorService, MessageSource messageSource){
            this.jiraConnectorService = jiraConnectorService;
        }
    
    
        @GetMapping("/healthDtl")
        @ResponseBody
        public ResponseEntity<HealthDtl> healthDtl() {
            logger.info("/jira/healthDtl endpoint called");
    
            HealthDtl health = new HealthDtl();
            ResponseTimeData data = new ResponseTimeData();
            try {
                data = jiraConnectorService.getResponseTime();
                if(data.getHttpStatusCode() == HttpStatus.OK.value())
                    health.setStatus("UP");
                else
                    health.setStatus("DOWN");
                health.setMessage(data.getMessage());
                health.setResponseTimeMs(data.getTime());
            } catch (UnirestException e) {
                logger.error(e.getLocalizedMessage(), e);
                health.setStatus("DOWN");
                health.setMessage(e.getMessage());
            }
            health.setHttpStatusCode(data.getHttpStatusCode());
    
            return new ResponseEntity<>(health, HttpStatus.OK);
        }
    }
    


    이제 다음과 같이 응답하는 새 액추에이터 끝점/management/jira/healthDtl이 있습니다.

    {
    "status":"UP",
    "httpStatusCode":200,
    "message":"",
    "responseTimeMs":369
    }
    


    이 사용자 지정 액추에이터 끝점을 단위 테스트하는 방법에 대한 새 게시물을 추가하겠습니다.

    좋은 웹페이지 즐겨찾기