Merge branch 'jenkins_with_weblogic' of http://192.168.240.178:18080/eapim/eapim-online.git into jenkins_with_weblogic

This commit is contained in:
cho
2026-02-19 15:53:51 +09:00
4 changed files with 60 additions and 61 deletions
@@ -1,5 +1,7 @@
package com.eactive.eai.custom.statistics;
import java.time.LocalDateTime;
import org.springframework.stereotype.Component;
import com.eactive.eai.common.message.EAIMessage;
@@ -120,6 +122,10 @@ public class ApiStatsMonitorImpl implements StatisticsMonitor {
private long extractResponseTime(EAIMessage msg) {
long msgPssTm = msg.getMsgPssTm(); // 메시지 처리시각
long msgRcvTm = msg.getMsgRcvTm(); // 메시지 수신시각
if (msgPssTm == 0) {
msgPssTm = System.currentTimeMillis();
}
if (msgPssTm > 0 && msgRcvTm > 0) {
return msgPssTm - msgRcvTm;
@@ -17,7 +17,6 @@ import com.eactive.eai.data.entity.custom.statistics.ApiStatsHour;
import com.eactive.eai.data.entity.custom.statistics.ApiStatsMinute;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* API 통계 수집기
@@ -60,80 +59,74 @@ public class ApiStatsCollector {
}
/**
* 거래 이벤트 기록 (시간 지정 - 테스트용)
* 거래 이벤트 기록 (시간 지정)
*
* @param event 거래 이벤트
* @param eventTime 이벤트 발생 시간
*/
public void recordEvent(TransactionEvent event, LocalDateTime eventTime) {
// 통계 수집 비활성화 체크 (분단위 또는 시간별 중 하나라도 활성화되어야 함)
boolean minuteEnabled = apiStatsConfig.isMinuteEnabled();
boolean hourEnabled = apiStatsConfig.isHourEnabled();
if (!minuteEnabled && !hourEnabled) {
if (log.isDebugEnabled()) {
log.debug("API stats collection is disabled (both minute and hour)");
}
log.debug("API stats collection is disabled (both minute and hour)");
return;
}
if (minuteEnabled) {
recordMinuteEvent(event, eventTime);
}
if (hourEnabled) {
recordHourEvent(event, eventTime);
}
}
private void recordMinuteEvent(TransactionEvent event, LocalDateTime eventTime) {
try {
MinuteStatsKey minuteKey = null;
MinuteStatsAggregator minuteAggregator = null;
HourStatsKey hourKey = null;
HourStatsAggregator hourAggregator = null;
if (minuteAggregators.size() >= MAX_MINUTE_AGGREGATORS) {
log.warn("Minute aggregator limit reached ({}), forcing flush of completed minutes", MAX_MINUTE_AGGREGATORS);
flushCompletedMinutes();
// 분단위 집계 (활성화된 경우만)
if (minuteEnabled) {
// Aggregator 개수 제한 체크 (메모리 보호)
if (minuteAggregators.size() >= MAX_MINUTE_AGGREGATORS) {
log.warn("Minute aggregator limit reached ({}), forcing flush of completed minutes", MAX_MINUTE_AGGREGATORS);
flushCompletedMinutes();
// flush 후에도 여전히 제한 초과 시 경고
if (minuteAggregators.size() >= MAX_MINUTE_AGGREGATORS) {
log.error("Minute aggregator count still exceeds limit after flush: {}", minuteAggregators.size());
}
log.error("Minute aggregator count still exceeds limit after flush: {}", minuteAggregators.size());
}
minuteKey = MinuteStatsKey.from(event, eventTime);
minuteAggregator = minuteAggregators.computeIfAbsent(
minuteKey,
MinuteStatsAggregator::new
);
minuteAggregator.recordEvent(event);
}
// 시간별 집계 (활성화된 경우만)
if (hourEnabled) {
// Aggregator 개수 제한 체크 (메모리 보호)
if (hourAggregators.size() >= MAX_HOUR_AGGREGATORS) {
log.warn("Hour aggregator limit reached ({}), forcing flush of completed hours", MAX_HOUR_AGGREGATORS);
flushCompletedHours();
// flush 후에도 여전히 제한 초과 시 경고
if (hourAggregators.size() >= MAX_HOUR_AGGREGATORS) {
log.error("Hour aggregator count still exceeds limit after flush: {}", hourAggregators.size());
}
}
hourKey = HourStatsKey.from(event, eventTime);
hourAggregator = hourAggregators.computeIfAbsent(
hourKey,
HourStatsAggregator::new
);
hourAggregator.recordEvent(event);
}
if (log.isDebugEnabled()) {
log.debug("Recorded event: minute={}, hour={}, minute_total={}, hour_total={}",
minuteKey, hourKey,
minuteAggregator != null ? minuteAggregator.getTotalCount() : 0,
hourAggregator != null ? hourAggregator.getTotalCount() : 0);
}
MinuteStatsKey minuteKey = MinuteStatsKey.from(event, eventTime);
MinuteStatsAggregator minuteAggregator = minuteAggregators.computeIfAbsent(
minuteKey,
MinuteStatsAggregator::new
);
minuteAggregator.recordEvent(event);
log.debug("Recorded minute event: key={}, total={}", minuteKey, minuteAggregator.getTotalCount());
} catch (Exception e) {
log.error("Failed to record event: {}", event, e);
log.error("Failed to record minute event: {}", event, e);
}
}
private void recordHourEvent(TransactionEvent event, LocalDateTime eventTime) {
try {
if (hourAggregators.size() >= MAX_HOUR_AGGREGATORS) {
log.warn("Hour aggregator limit reached ({}), forcing flush of completed hours", MAX_HOUR_AGGREGATORS);
flushCompletedHours();
if (hourAggregators.size() >= MAX_HOUR_AGGREGATORS) {
log.error("Hour aggregator count still exceeds limit after flush: {}", hourAggregators.size());
}
}
HourStatsKey hourKey = HourStatsKey.from(event, eventTime);
HourStatsAggregator hourAggregator = hourAggregators.computeIfAbsent(
hourKey,
HourStatsAggregator::new
);
hourAggregator.recordEvent(event);
log.debug("Recorded hour event: key={}, total={}", hourKey, hourAggregator.getTotalCount());
} catch (Exception e) {
log.error("Failed to record hour event: {}", event, e);
}
}
@@ -57,7 +57,6 @@ public class HourStatsAggregator {
/**
* 거래 이벤트 기록
* - AtomicLong 사용으로 synchronized 불필요 (성능 최적화)
*/
public void recordEvent(TransactionEvent event) {
int logSeq = event.getLogSequence();
@@ -194,6 +193,7 @@ public class HourStatsAggregator {
long timeout = timeoutCnt.get();
long systemErr = systemErrCnt.get();
long bizErr = bizErrCnt.get();
long avgCount = success + timeout + systemErr + bizErr;
stats.setTotalCnt(total);
stats.setSuccessCnt(success);
@@ -207,9 +207,9 @@ public class HourStatsAggregator {
stats.setSeq900BizErrCnt(seq900BizErrCnt.get());
// 응답시간 메트릭
if (total > 0 && totalRespTime.get() > 0) {
if (avgCount > 0 && totalRespTime.get() > 0) {
// 응답시간이 실제로 기록된 경우만 처리
double avg = (double) totalRespTime.get() / total;
double avg = (double) totalRespTime.get() / avgCount;
stats.setAvgRespTime(BigDecimal.valueOf(avg).setScale(3, RoundingMode.HALF_UP));
// Min/Max (totalRespTime > 0이면 반드시 갱신됨)
@@ -57,7 +57,6 @@ public class MinuteStatsAggregator {
/**
* 거래 이벤트 기록
* - AtomicLong 사용으로 synchronized 불필요 (성능 최적화)
*/
public void recordEvent(TransactionEvent event) {
int logSeq = event.getLogSequence();
@@ -194,6 +193,7 @@ public class MinuteStatsAggregator {
long timeout = timeoutCnt.get();
long systemErr = systemErrCnt.get();
long bizErr = bizErrCnt.get();
long avgCount = success + timeout + systemErr + bizErr;
stats.setTotalCnt(total);
stats.setSuccessCnt(success);
@@ -207,9 +207,9 @@ public class MinuteStatsAggregator {
stats.setSeq900BizErrCnt(seq900BizErrCnt.get());
// 응답시간 메트릭
if (total > 0 && totalRespTime.get() > 0) {
if (avgCount > 0 && totalRespTime.get() > 0) {
// 응답시간이 실제로 기록된 경우만 처리
double avg = (double) totalRespTime.get() / total;
double avg = (double) totalRespTime.get() / avgCount;
stats.setAvgRespTime(BigDecimal.valueOf(avg).setScale(3, RoundingMode.HALF_UP));
// Min/Max (totalRespTime > 0이면 반드시 갱신됨)