API상태변화감시JOB api.status.if_id_로 시작하는 파라미터가 있는 경우 감시조건에 if_id 추가
eapim-admin CI / build (push) Waiting to run

This commit is contained in:
eastargh
2026-09-17 17:45:18 +09:00
parent 65c1593b97
commit 0a4b92ed7a
3 changed files with 87 additions and 5 deletions
@@ -73,6 +73,9 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
+ " BETWEEN TO_CHAR(:delayRangeStart,'YYYYMMDDHH24MI')"
+ " AND TO_CHAR(:rangeEnd,'YYYYMMDDHH24MI'))) AS DELAY_YN"
+ " FROM TSEAIHE01 A LEFT OUTER JOIN API_STATUS B ON A.EAISVCNAME = B.EAISVCNAME"
// apiIdsProvided='N'이면 전체 API 대상(무조건 참), 'Y'면 apiIds로 좁힌다.
// (apiIds는 :apiIdsProvided='N'일 때도 항상 바인딩되어야 하므로 이 경우 호출측에서 더미 1건을 채워 보낸다)
+ " WHERE (:apiIdsProvided = 'N' OR A.EAISVCNAME IN (:apiIds))"
+ " )"
+ " ) A WHERE EVENT != 'STAY'")
List<ApiStatusEvent> findApiStatusEvents(
@@ -80,7 +83,9 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
@Param("delayAvgRespTime") int delayAvgRespTime,
@Param("errorRangeStart") LocalDateTime errorRangeStart,
@Param("delayRangeStart") LocalDateTime delayRangeStart,
@Param("rangeEnd") LocalDateTime rangeEnd
@Param("rangeEnd") LocalDateTime rangeEnd,
@Param("apiIdsProvided") String apiIdsProvided,
@Param("apiIds") Collection<String> apiIds
);
/**
@@ -113,6 +118,23 @@ public interface ApiStatusRepository extends BaseRepository<ApiStatus, String> {
@Param("modifiedBy") String modifiedBy,
@Param("modifiedDate") LocalDateTime modifiedDate);
/**
* API 상태 변경 히스토리 적재. {@code claimStatusChange}로 선점에 성공한 실행에서만
* (즉 실제로 상태가 바뀐 건에 대해서만) 1행 기록한다.
*/
@Modifying
@Query(nativeQuery = true, value =
"INSERT INTO API_STATUS_HIST" +
" (HIST_SEQ, EAISVCNAME, STATUS_CODE, PREV_STATUS_CODE, JOBNAME, INSTANCENAME, CREATED_BY, CREATED_DATE)" +
" VALUES (API_STATUS_HIST_SEQ.NEXTVAL, :eaisvcname, :statusCode, :prevStatusCode, :jobName, :instanceName, :createdBy, :createdDate)")
void insertHistory(@Param("eaisvcname") String eaisvcname,
@Param("statusCode") String statusCode,
@Param("prevStatusCode") String prevStatusCode,
@Param("jobName") String jobName,
@Param("instanceName") String instanceName,
@Param("createdBy") String createdBy,
@Param("createdDate") LocalDateTime createdDate);
/**
* 판정 구간에 트래픽이 있는 API 의 오류율·지연 판정값. 개발 모드(-Deai.systemmode=D) 진단 로그 전용.
*
@@ -7,6 +7,7 @@ import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -69,7 +70,7 @@ public class ApiStatusService {
}
public void updateApiStatus(HashMap<String, String> param) {
public void updateApiStatus(HashMap<String, String> param, List<String> targetApiIds, String jobName) {
int errorRate = Integer.parseInt(param.get("errorRate"));
int errorRangeMinute = Integer.parseInt(param.get("errorRangeMinute"));
@@ -86,12 +87,18 @@ public class ApiStatusService {
LocalDateTime errorRangeStart = rangeEnd.minusMinutes(errorRangeMinute);
LocalDateTime delayRangeStart = rangeEnd.minusMinutes(delayRangeMinute);
// targetApiIds가 비어있으면 전체 API 대상, 값이 있으면 그 API들로만 판정 대상을 좁힌다
// (JobDataMap의 api.status.if_id_ 로 시작하는 파라미터들의 값 - ApiStatusMonitorJob 참고)
boolean apiIdsProvided = targetApiIds != null && !targetApiIds.isEmpty();
List<ApiStatusEvent> list = apiStatusRepository.findApiStatusEvents(
errorRate,
delayAvgRespTime,
errorRangeStart,
delayRangeStart,
rangeEnd
rangeEnd,
apiIdsProvided ? "Y" : "N",
apiIdsProvided ? targetApiIds : Collections.singletonList("")
);
HashMap<String, List<String>> eventMap = new HashMap<>();
@@ -110,6 +117,15 @@ public class ApiStatusService {
log.debug("API 상태 변경: {}-{} {} → {}", event.getEaisvcname(), event.getEaisvcdesc(), event.getEvent(), newStatusCode);
// API 상태 변경 히스토리 적재 (선점에 성공한 실행에서만 - 실제 상태 전이 1건당 1행)
apiStatusRepository.insertHistory(
event.getEaisvcname(),
newStatusCode,
event.getPrevStatusCode(),
jobName,
System.getProperty("inst.Name"),
"SCHEDULER",
LocalDateTime.now());
//이벤트별로 api분리 저장
List<String> apis = (List<String>)eventMap.get(event.getEvent());
@@ -1,7 +1,9 @@
package com.eactive.eai.rms.ext.djb.job;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -39,6 +41,8 @@ import com.eactive.eai.rms.onl.common.util.DateUtil;
* <b>api.status.error.rate</b>: API 장애기준 오류건수 비율(%) (단위: 시간, 기본값: 100)
* <b>api.status.delay.range_minute</b>: API 지연기준 판단 시간간격 (단위: 분, 기본값: 1)
* <b>api.status.delay.avg_resp_time</b>: API 지연기준 평균응답시간 (단위: 밀리세컨드, 기본값: 10000)
* <b>api.status.if_id_*</b>: 판정 대상 API ID(인터페이스ID). 여러 개면 접두사가 같은 키를
* 여러 개 등록(api.status.if_id_1, api.status.if_id_2, ...). 미등록 시 전체 API 대상.
* </li>
* </ul>
*
@@ -65,6 +69,14 @@ public class ApiStatusMonitorJob implements Job {
/** Job 파라미터 키: API 지연기준 평균응답시간(ms) */
public static final String KEY_API_STATUS_DELAY_AVG_RESP_TIME = "api.status.delay.avg_resp_time";
/**
* Job 파라미터 키 접두사: 판정 대상 API ID(인터페이스ID) 목록.
* JobDataMap은 배열을 담을 수 없어, 이 접두사로 시작하는 키를 여러 개 등록하면
* (예: api.status.if_id_1, api.status.if_id_2, ...) 그 값들을 모아 배열로 취급한다.
* 값이 하나도 없으면(=전체 등록 안 함) 기존처럼 전체 API가 판정 대상이다.
*/
public static final String KEY_API_STATUS_IF_ID_PREFIX = "api.status.if_id_";
public static final String DEFAULT_ERROR_RANGE_MINUTE = "1";
public static final String DEFAULT_ERROR_RATE = "100";
public static final String DEFAULT_DELAY_RANGE_MINUTE = "1";
@@ -96,6 +108,11 @@ public class ApiStatusMonitorJob implements Job {
HashMap<String, String> param = this.checkParameters(jobDataMap);
//다른 조건으로 특정 API들을 감시하기 위해 Job을 다른이름으로 등록하여 추가로 감시한다.
//파라미터에 api.status.if_id_(n)=ASCORBED000S1 을 필요한 만큼 추가한다(최대 500개)
List<String> apiIds = this.collectApiIds(jobDataMap);
String jobName = context.getJobDetail().getKey().getName();
ApplicationContext appContext;
try {
@@ -111,7 +128,7 @@ public class ApiStatusMonitorJob implements Job {
DataSourceContextHolder.setDataSourceType(
DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));
try {
apiStatusUpdateService.updateApiStatus(param);
apiStatusUpdateService.updateApiStatus(param, apiIds, jobName);
} catch (Exception e) {
log.error("ApiStatusUpdateJob execution failed", e);
@@ -184,6 +201,33 @@ public class ApiStatusMonitorJob implements Job {
return param;
}
/**
* KEY_API_STATUS_IF_ID_PREFIX(api.status.if_id_)로 시작하는 Job 파라미터들의 값을 모아
* 판정 대상 API ID 목록을 만든다. JobDataMap은 배열을 지원하지 않아 접두사 붙은 키를
* 여러 개 등록하는 방식으로 배열을 흉내낸다. 값이 없으면(=아무 키도 등록 안 함) 빈 리스트를
* 반환하며, 이 경우 {@code ApiStatusService.updateApiStatus}는 전체 API를 판정 대상으로 삼는다.
*/
private List<String> collectApiIds(JobDataMap jobDataMap) {
List<String> apiIds = new ArrayList<>();
if (jobDataMap == null) {
return apiIds;
}
for (String key : jobDataMap.getKeys()) {
if (!key.startsWith(KEY_API_STATUS_IF_ID_PREFIX)) {
continue;
}
String value = jobDataMap.getString(key);
if (StringUtils.isNotBlank(value)) {
apiIds.add(value.trim());
}
}
return apiIds;
}
/**
* 개발 모드 여부 확인
* @return eai.systemmode=D 이면 true