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