diff --git a/src/main/java/com/eactive/eai/rms/ext/djb/job/ApiStatsHourlyAggregationJob.java b/src/main/java/com/eactive/eai/rms/ext/djb/job/ApiStatsHourlyAggregationJob.java index 33d1fe2..086d4f0 100644 --- a/src/main/java/com/eactive/eai/rms/ext/djb/job/ApiStatsHourlyAggregationJob.java +++ b/src/main/java/com/eactive/eai/rms/ext/djb/job/ApiStatsHourlyAggregationJob.java @@ -1,8 +1,9 @@ package com.eactive.eai.rms.ext.djb.job; import java.time.LocalDate; -import java.time.LocalTime; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @@ -28,7 +29,8 @@ import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsHour; /** * API 로그 테이블을 시간별 통계로 집계하는 배치 작업 * TSEAILGXX → API_STATS_HOUR - * 실행 주기: 매시 00:10 (당일 데이터 집계) + * 실행 주기: 매시 00:10, 직전 1시간(예: 14:10 실행 시 13:00~13:59:59) 데이터만 집계 + * (0시대 실행 시 전날 23:00~23:59:59 집계) */ @Component public class ApiStatsHourlyAggregationJob implements Job { @@ -59,11 +61,9 @@ public class ApiStatsHourlyAggregationJob implements Job { DataSourceType dataType = DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW); DataSourceContextHolder.setDataSourceType(dataType); try { - LocalDate targetDate = LocalDate.now(); - if (LocalTime.now().isBefore(LocalTime.of(1, 0))) { - targetDate = targetDate.minusDays(1); - } - selfJob.executeManual(targetDate); + // 직전 1시간(예: 14:10 실행 -> 13:00~13:59:59). 0시대 실행 시 자동으로 전날 23시로 롤오버됨 + LocalDateTime targetHour = LocalDateTime.now().minusHours(1).truncatedTo(ChronoUnit.HOURS); + selfJob.executeManual(targetHour); } catch (Exception e) { throw new JobExecutionException(e); } finally { @@ -72,22 +72,38 @@ public class ApiStatsHourlyAggregationJob implements Job { } /** - * 수동 실행 메서드 (날짜 지정) + * 수동 실행 메서드 (날짜 지정, 하루 전체 재집계 - 관리자 화면 백필용) */ @Transactional public int executeManual(LocalDate targetDate) { + LocalDateTime rangeStart = targetDate.atStartOfDay(); + return aggregate(rangeStart, rangeStart.plusDays(1)); + } + + /** + * 수동/스케줄 실행 메서드 (시각 지정, 해당 시각이 속한 1시간만 집계) + */ + @Transactional + public int executeManual(LocalDateTime targetHour) { + LocalDateTime rangeStart = targetHour.truncatedTo(ChronoUnit.HOURS); + return aggregate(rangeStart, rangeStart.plusHours(1)); + } + + private int aggregate(LocalDateTime rangeStart, LocalDateTime rangeEnd) { long startTime = System.currentTimeMillis(); - log.info("=== 시간별 통계 집계 작업 시작 === 대상: {}", targetDate); + log.info("=== 시간별 통계 집계 작업 시작 === 대상: {} ~ {}", rangeStart, rangeEnd); - String searchDate = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")); - String logTableName = CommonUtil.getLogTable(searchDate, true); + DateTimeFormatter tsFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String logTableName = CommonUtil.getLogTable(rangeStart.format(DateTimeFormatter.ofPattern("yyyyMMdd")), true); + String rangeStartStr = rangeStart.format(tsFormat) + "000"; + String rangeEndStr = rangeEnd.format(tsFormat) + "000"; - // 1. 기존 데이터 삭제 + // 1. 대상 구간(rangeStart ~ rangeEnd)의 기존 데이터만 삭제 (다른 시간대 데이터는 보존) QApiStatsHour q = QApiStatsHour.apiStatsHour; long deletedCount = apiStatsHourService.getJPAQueryFactory() .delete(q) - .where(q.statTime.goe(targetDate.atStartOfDay()) - .and(q.statTime.lt(targetDate.plusDays(1).atStartOfDay()))) + .where(q.statTime.goe(rangeStart) + .and(q.statTime.lt(rangeEnd))) .execute(); log.info("기존 데이터 삭제: {} 건", deletedCount); @@ -130,14 +146,15 @@ public class ApiStatsHourlyAggregationJob implements Job { " , MAX(CASE WHEN LOGPRCSSSERNO = '400' THEN LOGPRCSSSERNO ELSE '' END) AS E400" + " , MAX(EAIERRCD) AS ERROR_CODE" + " FROM " + logTableName + - " WHERE MSGDPSTYMS LIKE :searchDate || '%'" + + " WHERE MSGDPSTYMS >= :rangeStart AND MSGDPSTYMS < :rangeEnd" + " GROUP BY EAISVCSERNO" + " ) A LEFT OUTER JOIN TSEAICM20 B ON A.ERROR_CODE = B.CODE AND B.CODEGROUP = 'ERRCODE_TIMEOUT' AND B.USEYN = 'Y' " + " GROUP BY SUBSTR(DT,1,10), API_NAME, GW_INSTANCE_ID, BIZ_DIV_CODE, NVL(A.CLIENT_ID, 'NONE')" + " , INBOUND_ADAPTER, OUTBOUND_ADAPTER"; int savedCount = entityManager.createNativeQuery(sql) - .setParameter("searchDate", searchDate) + .setParameter("rangeStart", rangeStartStr) + .setParameter("rangeEnd", rangeEndStr) .executeUpdate(); long elapsedTime = System.currentTimeMillis() - startTime;