API명별 요약 통계
This commit is contained in:
+112
@@ -1,11 +1,14 @@
|
||||
package com.eactive.eai.rms.data.entity.onl.kjb.statistics;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -13,8 +16,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.eactive.eai.data.jpa.AbstractDataService;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsChartUI;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsSearch;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsUI;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -87,6 +92,113 @@ public class ApiStatsDayService
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 조회 (GROUP BY apiName)
|
||||
*/
|
||||
public Page<ApiStatsUI> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
QApiStatsDay q = QApiStatsDay.apiStatsDay;
|
||||
BooleanBuilder builder = buildSearchConditions(q, search);
|
||||
|
||||
// 전체 건수 조회
|
||||
Long total = getJPAQueryFactory()
|
||||
.select(q.apiName.countDistinct())
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.fetchOne();
|
||||
|
||||
// 페이징 적용하여 조회
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
// 가중 평균: SUM(avg * successCnt) / SUM(successCnt)
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return new PageImpl<>(results, pageable, total != null ? total.longValue() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 전체 조회 (Excel용)
|
||||
*/
|
||||
public List<ApiStatsUI> selectSummaryListForExcel(ApiStatsSearch search) {
|
||||
QApiStatsDay q = QApiStatsDay.apiStatsDay;
|
||||
BooleanBuilder builder = buildSearchConditions(q, search);
|
||||
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private BooleanBuilder buildSearchConditions(QApiStatsDay q, ApiStatsSearch search) {
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
|
||||
+172
@@ -1,11 +1,14 @@
|
||||
package com.eactive.eai.rms.data.entity.onl.kjb.statistics;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -13,8 +16,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.eactive.eai.data.jpa.AbstractDataService;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsChartUI;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsSearch;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsUI;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -148,6 +153,173 @@ public class ApiStatsHourService
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 조회 (GROUP BY apiName)
|
||||
*/
|
||||
public Page<ApiStatsUI> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
QApiStatsHour q = QApiStatsHour.apiStatsHour;
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
calculateDateRange(search);
|
||||
if (search.getParsedStartDateTime() != null) {
|
||||
builder.and(q.statTime.goe(search.getParsedStartDateTime()));
|
||||
builder.and(q.statTime.loe(search.getParsedEndDateTime()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchApiName())) {
|
||||
builder.and(q.apiName.containsIgnoreCase(search.getSearchApiName()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchGwInstanceId())) {
|
||||
builder.and(q.gwInstanceId.containsIgnoreCase(search.getSearchGwInstanceId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchBizDivCode())) {
|
||||
builder.and(q.bizDivCode.containsIgnoreCase(search.getSearchBizDivCode()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchClientId())) {
|
||||
builder.and(q.clientId.containsIgnoreCase(search.getSearchClientId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchInboundAdapter())) {
|
||||
builder.and(q.inboundAdapter.containsIgnoreCase(search.getSearchInboundAdapter()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchOutboundAdapter())) {
|
||||
builder.and(q.outboundAdapter.containsIgnoreCase(search.getSearchOutboundAdapter()));
|
||||
}
|
||||
|
||||
// 전체 건수 조회
|
||||
Long total = getJPAQueryFactory()
|
||||
.select(q.apiName.countDistinct())
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.fetchOne();
|
||||
|
||||
// 페이징 적용하여 조회
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
// 가중 평균: SUM(avg * successCnt) / SUM(successCnt)
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return new PageImpl<>(results, pageable, total != null ? total.longValue() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 전체 조회 (Excel용)
|
||||
*/
|
||||
public List<ApiStatsUI> selectSummaryListForExcel(ApiStatsSearch search) {
|
||||
QApiStatsHour q = QApiStatsHour.apiStatsHour;
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
calculateDateRange(search);
|
||||
if (search.getParsedStartDateTime() != null) {
|
||||
builder.and(q.statTime.goe(search.getParsedStartDateTime()));
|
||||
builder.and(q.statTime.loe(search.getParsedEndDateTime()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchApiName())) {
|
||||
builder.and(q.apiName.containsIgnoreCase(search.getSearchApiName()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchGwInstanceId())) {
|
||||
builder.and(q.gwInstanceId.containsIgnoreCase(search.getSearchGwInstanceId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchBizDivCode())) {
|
||||
builder.and(q.bizDivCode.containsIgnoreCase(search.getSearchBizDivCode()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchClientId())) {
|
||||
builder.and(q.clientId.containsIgnoreCase(search.getSearchClientId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchInboundAdapter())) {
|
||||
builder.and(q.inboundAdapter.containsIgnoreCase(search.getSearchInboundAdapter()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchOutboundAdapter())) {
|
||||
builder.and(q.outboundAdapter.containsIgnoreCase(search.getSearchOutboundAdapter()));
|
||||
}
|
||||
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 기간 계산 (최대 24시간 제한)
|
||||
*/
|
||||
|
||||
+173
@@ -1,11 +1,15 @@
|
||||
package com.eactive.eai.rms.data.entity.onl.kjb.statistics;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -13,8 +17,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.eactive.eai.data.jpa.AbstractDataService;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsChartUI;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsSearch;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsUI;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -150,6 +156,173 @@ public class ApiStatsMinuteService
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 조회 (GROUP BY apiName)
|
||||
*/
|
||||
public Page<ApiStatsUI> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
QApiStatsMinute q = QApiStatsMinute.apiStatsMinute;
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
calculateDateRange(search);
|
||||
if (search.getParsedStartDateTime() != null) {
|
||||
builder.and(q.statTime.goe(search.getParsedStartDateTime()));
|
||||
builder.and(q.statTime.loe(search.getParsedEndDateTime()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchApiName())) {
|
||||
builder.and(q.apiName.containsIgnoreCase(search.getSearchApiName()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchGwInstanceId())) {
|
||||
builder.and(q.gwInstanceId.containsIgnoreCase(search.getSearchGwInstanceId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchBizDivCode())) {
|
||||
builder.and(q.bizDivCode.containsIgnoreCase(search.getSearchBizDivCode()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchClientId())) {
|
||||
builder.and(q.clientId.containsIgnoreCase(search.getSearchClientId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchInboundAdapter())) {
|
||||
builder.and(q.inboundAdapter.containsIgnoreCase(search.getSearchInboundAdapter()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchOutboundAdapter())) {
|
||||
builder.and(q.outboundAdapter.containsIgnoreCase(search.getSearchOutboundAdapter()));
|
||||
}
|
||||
|
||||
// 전체 건수 조회
|
||||
Long total = getJPAQueryFactory()
|
||||
.select(q.apiName.countDistinct())
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.fetchOne();
|
||||
|
||||
// 페이징 적용하여 조회
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
// 가중 평균: SUM(avg * successCnt) / SUM(successCnt)
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return new PageImpl<>(results, pageable, total != null ? total.longValue() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 전체 조회 (Excel용)
|
||||
*/
|
||||
public List<ApiStatsUI> selectSummaryListForExcel(ApiStatsSearch search) {
|
||||
QApiStatsMinute q = QApiStatsMinute.apiStatsMinute;
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
calculateDateRange(search);
|
||||
if (search.getParsedStartDateTime() != null) {
|
||||
builder.and(q.statTime.goe(search.getParsedStartDateTime()));
|
||||
builder.and(q.statTime.loe(search.getParsedEndDateTime()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchApiName())) {
|
||||
builder.and(q.apiName.containsIgnoreCase(search.getSearchApiName()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchGwInstanceId())) {
|
||||
builder.and(q.gwInstanceId.containsIgnoreCase(search.getSearchGwInstanceId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchBizDivCode())) {
|
||||
builder.and(q.bizDivCode.containsIgnoreCase(search.getSearchBizDivCode()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchClientId())) {
|
||||
builder.and(q.clientId.containsIgnoreCase(search.getSearchClientId()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchInboundAdapter())) {
|
||||
builder.and(q.inboundAdapter.containsIgnoreCase(search.getSearchInboundAdapter()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(search.getSearchOutboundAdapter())) {
|
||||
builder.and(q.outboundAdapter.containsIgnoreCase(search.getSearchOutboundAdapter()));
|
||||
}
|
||||
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 기간 계산 (최대 1시간 제한)
|
||||
*/
|
||||
|
||||
+112
@@ -1,11 +1,14 @@
|
||||
package com.eactive.eai.rms.data.entity.onl.kjb.statistics;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.YearMonth;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -13,8 +16,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.eactive.eai.data.jpa.AbstractDataService;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsChartUI;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsSearch;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsUI;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -87,6 +92,113 @@ public class ApiStatsMonthService
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 조회 (GROUP BY apiName)
|
||||
*/
|
||||
public Page<ApiStatsUI> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
QApiStatsMonth q = QApiStatsMonth.apiStatsMonth;
|
||||
BooleanBuilder builder = buildSearchConditions(q, search);
|
||||
|
||||
// 전체 건수 조회
|
||||
Long total = getJPAQueryFactory()
|
||||
.select(q.apiName.countDistinct())
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.fetchOne();
|
||||
|
||||
// 페이징 적용하여 조회
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
// 가중 평균: SUM(avg * successCnt) / SUM(successCnt)
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return new PageImpl<>(results, pageable, total != null ? total.longValue() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 전체 조회 (Excel용)
|
||||
*/
|
||||
public List<ApiStatsUI> selectSummaryListForExcel(ApiStatsSearch search) {
|
||||
QApiStatsMonth q = QApiStatsMonth.apiStatsMonth;
|
||||
BooleanBuilder builder = buildSearchConditions(q, search);
|
||||
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private BooleanBuilder buildSearchConditions(QApiStatsMonth q, ApiStatsSearch search) {
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
|
||||
+112
@@ -1,10 +1,13 @@
|
||||
package com.eactive.eai.rms.data.entity.onl.kjb.statistics;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.Year;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -12,8 +15,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.eactive.eai.data.jpa.AbstractDataService;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsChartUI;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsSearch;
|
||||
import com.eactive.ext.kjb.statistics.ui.ApiStatsUI;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -84,6 +89,113 @@ public class ApiStatsYearService
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 조회 (GROUP BY apiName)
|
||||
*/
|
||||
public Page<ApiStatsUI> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
QApiStatsYear q = QApiStatsYear.apiStatsYear;
|
||||
BooleanBuilder builder = buildSearchConditions(q, search);
|
||||
|
||||
// 전체 건수 조회
|
||||
Long total = getJPAQueryFactory()
|
||||
.select(q.apiName.countDistinct())
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.fetchOne();
|
||||
|
||||
// 페이징 적용하여 조회
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
// 가중 평균: SUM(avg * successCnt) / SUM(successCnt)
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return new PageImpl<>(results, pageable, total != null ? total.longValue() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* API명별 요약 통계 전체 조회 (Excel용)
|
||||
*/
|
||||
public List<ApiStatsUI> selectSummaryListForExcel(ApiStatsSearch search) {
|
||||
QApiStatsYear q = QApiStatsYear.apiStatsYear;
|
||||
BooleanBuilder builder = buildSearchConditions(q, search);
|
||||
|
||||
List<ApiStatsUI> results = getJPAQueryFactory()
|
||||
.select(Projections.fields(ApiStatsUI.class,
|
||||
q.apiName,
|
||||
q.totalCnt.sum().as("totalCnt"),
|
||||
q.successCnt.sum().as("successCnt"),
|
||||
q.timeoutCnt.sum().as("timeoutCnt"),
|
||||
q.systemErrCnt.sum().as("systemErrCnt"),
|
||||
q.bizErrCnt.sum().as("bizErrCnt"),
|
||||
q.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
q.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
q.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
q.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
q.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
Expressions.cases()
|
||||
.when(q.successCnt.sum().gt(0))
|
||||
.then(q.avgRespTime.multiply(q.successCnt).sum()
|
||||
.divide(q.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime")))
|
||||
.from(q)
|
||||
.where(builder)
|
||||
.groupBy(q.apiName)
|
||||
.orderBy(q.apiName.asc())
|
||||
.fetch();
|
||||
|
||||
// 소수점 3자리로 반올림
|
||||
results.forEach(ui -> {
|
||||
if (ui.getAvgRespTime() != null) {
|
||||
ui.setAvgRespTime(ui.getAvgRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMinRespTime() != null) {
|
||||
ui.setMinRespTime(ui.getMinRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
if (ui.getMaxRespTime() != null) {
|
||||
ui.setMaxRespTime(ui.getMaxRespTime().setScale(3, RoundingMode.HALF_UP));
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private BooleanBuilder buildSearchConditions(QApiStatsYear q, ApiStatsSearch search) {
|
||||
BooleanBuilder builder = new BooleanBuilder();
|
||||
|
||||
|
||||
@@ -63,6 +63,12 @@ public class ApiStatsDayController {
|
||||
return ResponseEntity.ok(chartData);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsDayMan.json", params = "cmd=LIST_SUMMARY")
|
||||
public ResponseEntity<GridResponse<ApiStatsUI>> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
Page<ApiStatsUI> page = service.selectSummaryList(search, pageable);
|
||||
return ResponseEntity.ok(new GridResponse<>(page));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsDayMan.json", params = "cmd=EXCEL_EXPORT")
|
||||
public void exportToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export started - search: {}", search);
|
||||
@@ -106,10 +112,55 @@ public class ApiStatsDayController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsDayMan.json", params = "cmd=EXCEL_EXPORT_SUMMARY")
|
||||
public void exportSummaryToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export (summary) started - search: {}", search);
|
||||
|
||||
try {
|
||||
List<ApiStatsUI> dataList = service.selectSummaryListForExcel(search);
|
||||
log.info("Summary data retrieved - count: {}", dataList.size());
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
log.warn("No data found for export");
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}");
|
||||
response.getWriter().flush();
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = generateSummaryFileName(search);
|
||||
log.info("Generating Excel file: {}", fileName);
|
||||
|
||||
excelExportService.exportApiStats(dataList, fileName, response);
|
||||
log.info("Excel export (summary) completed successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel export (summary) failed - error: {}", e.getMessage(), e);
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}");
|
||||
response.getWriter().flush();
|
||||
} else {
|
||||
log.error("Cannot send error response - response already committed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String generateFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
return "API일별통계_" + timeRange + ".xlsx";
|
||||
}
|
||||
|
||||
private String generateSummaryFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
return "API일별통계_요약_" + timeRange + ".xlsx";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,12 @@ public class ApiStatsHourController {
|
||||
return ResponseEntity.ok(chartData);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsHourMan.json", params = "cmd=LIST_SUMMARY")
|
||||
public ResponseEntity<GridResponse<ApiStatsUI>> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
Page<ApiStatsUI> page = service.selectSummaryList(search, pageable);
|
||||
return ResponseEntity.ok(new GridResponse<>(page));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsHourMan.json", params = "cmd=EXCEL_EXPORT")
|
||||
public void exportToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export started - search: {}", search);
|
||||
@@ -106,10 +112,55 @@ public class ApiStatsHourController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsHourMan.json", params = "cmd=EXCEL_EXPORT_SUMMARY")
|
||||
public void exportSummaryToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export (summary) started - search: {}", search);
|
||||
|
||||
try {
|
||||
List<ApiStatsUI> dataList = service.selectSummaryListForExcel(search);
|
||||
log.info("Summary data retrieved - count: {}", dataList.size());
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
log.warn("No data found for export");
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}");
|
||||
response.getWriter().flush();
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = generateSummaryFileName(search);
|
||||
log.info("Generating Excel file: {}", fileName);
|
||||
|
||||
excelExportService.exportApiStats(dataList, fileName, response);
|
||||
log.info("Excel export (summary) completed successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel export (summary) failed - error: {}", e.getMessage(), e);
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}");
|
||||
response.getWriter().flush();
|
||||
} else {
|
||||
log.error("Cannot send error response - response already committed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String generateFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH"));
|
||||
return "API시간별통계_" + timeRange + ".xlsx";
|
||||
}
|
||||
|
||||
private String generateSummaryFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH"));
|
||||
return "API시간별통계_요약_" + timeRange + ".xlsx";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,12 @@ public class ApiStatsMinuteController {
|
||||
return ResponseEntity.ok(chartData);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsMinuteMan.json", params = "cmd=LIST_SUMMARY")
|
||||
public ResponseEntity<GridResponse<ApiStatsUI>> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
Page<ApiStatsUI> page = service.selectSummaryList(search, pageable);
|
||||
return ResponseEntity.ok(new GridResponse<>(page));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsMinuteMan.json", params = "cmd=EXCEL_EXPORT")
|
||||
public void exportToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export started - search: {}", search);
|
||||
@@ -106,10 +112,55 @@ public class ApiStatsMinuteController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsMinuteMan.json", params = "cmd=EXCEL_EXPORT_SUMMARY")
|
||||
public void exportSummaryToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export (summary) started - search: {}", search);
|
||||
|
||||
try {
|
||||
List<ApiStatsUI> dataList = service.selectSummaryListForExcel(search);
|
||||
log.info("Summary data retrieved - count: {}", dataList.size());
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
log.warn("No data found for export");
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}");
|
||||
response.getWriter().flush();
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = generateSummaryFileName(search);
|
||||
log.info("Generating Excel file: {}", fileName);
|
||||
|
||||
excelExportService.exportApiStats(dataList, fileName, response);
|
||||
log.info("Excel export (summary) completed successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel export (summary) failed - error: {}", e.getMessage(), e);
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}");
|
||||
response.getWriter().flush();
|
||||
} else {
|
||||
log.error("Cannot send error response - response already committed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String generateFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
|
||||
return "API분단위통계_" + timeRange + ".xlsx";
|
||||
}
|
||||
|
||||
private String generateSummaryFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
|
||||
return "API분단위통계_요약_" + timeRange + ".xlsx";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,12 @@ public class ApiStatsMonthController {
|
||||
return ResponseEntity.ok(chartData);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=LIST_SUMMARY")
|
||||
public ResponseEntity<GridResponse<ApiStatsUI>> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
Page<ApiStatsUI> page = service.selectSummaryList(search, pageable);
|
||||
return ResponseEntity.ok(new GridResponse<>(page));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=EXCEL_EXPORT")
|
||||
public void exportToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export started - search: {}", search);
|
||||
@@ -106,10 +112,55 @@ public class ApiStatsMonthController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsMonthMan.json", params = "cmd=EXCEL_EXPORT_SUMMARY")
|
||||
public void exportSummaryToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export (summary) started - search: {}", search);
|
||||
|
||||
try {
|
||||
List<ApiStatsUI> dataList = service.selectSummaryListForExcel(search);
|
||||
log.info("Summary data retrieved - count: {}", dataList.size());
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
log.warn("No data found for export");
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}");
|
||||
response.getWriter().flush();
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = generateSummaryFileName(search);
|
||||
log.info("Generating Excel file: {}", fileName);
|
||||
|
||||
excelExportService.exportApiStats(dataList, fileName, response);
|
||||
log.info("Excel export (summary) completed successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel export (summary) failed - error: {}", e.getMessage(), e);
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}");
|
||||
response.getWriter().flush();
|
||||
} else {
|
||||
log.error("Cannot send error response - response already committed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String generateFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: YearMonth.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
|
||||
return "API월별통계_" + timeRange + ".xlsx";
|
||||
}
|
||||
|
||||
private String generateSummaryFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: YearMonth.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
|
||||
return "API월별통계_요약_" + timeRange + ".xlsx";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,12 @@ public class ApiStatsYearController {
|
||||
return ResponseEntity.ok(chartData);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsYearMan.json", params = "cmd=LIST_SUMMARY")
|
||||
public ResponseEntity<GridResponse<ApiStatsUI>> selectSummaryList(ApiStatsSearch search, Pageable pageable) {
|
||||
Page<ApiStatsUI> page = service.selectSummaryList(search, pageable);
|
||||
return ResponseEntity.ok(new GridResponse<>(page));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsYearMan.json", params = "cmd=EXCEL_EXPORT")
|
||||
public void exportToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export started - search: {}", search);
|
||||
@@ -105,10 +111,55 @@ public class ApiStatsYearController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/onl/kjb/statistics/apiStatsYearMan.json", params = "cmd=EXCEL_EXPORT_SUMMARY")
|
||||
public void exportSummaryToExcel(ApiStatsSearch search, HttpServletResponse response) throws IOException {
|
||||
log.info("Excel export (summary) started - search: {}", search);
|
||||
|
||||
try {
|
||||
List<ApiStatsUI> dataList = service.selectSummaryListForExcel(search);
|
||||
log.info("Summary data retrieved - count: {}", dataList.size());
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
log.warn("No data found for export");
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"조회된 데이터가 없습니다.\"}");
|
||||
response.getWriter().flush();
|
||||
return;
|
||||
}
|
||||
|
||||
String fileName = generateSummaryFileName(search);
|
||||
log.info("Generating Excel file: {}", fileName);
|
||||
|
||||
excelExportService.exportApiStats(dataList, fileName, response);
|
||||
log.info("Excel export (summary) completed successfully");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Excel export (summary) failed - error: {}", e.getMessage(), e);
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json; charset=UTF-8");
|
||||
response.getWriter().write("{\"message\":\"Excel 파일 생성 중 오류가 발생했습니다: " + e.getMessage() + "\"}");
|
||||
response.getWriter().flush();
|
||||
} else {
|
||||
log.error("Cannot send error response - response already committed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String generateFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: String.valueOf(Year.now().getValue());
|
||||
return "API연간통계_" + timeRange + ".xlsx";
|
||||
}
|
||||
|
||||
private String generateSummaryFileName(ApiStatsSearch search) {
|
||||
String timeRange = StringUtils.isNotBlank(search.getSearchStartDateTime())
|
||||
? search.getSearchStartDateTime()
|
||||
: String.valueOf(Year.now().getValue());
|
||||
return "API연간통계_요약_" + timeRange + ".xlsx";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.eactive.eai.rms.data.entity.onl.kjb.statistics.ApiStatsDayService;
|
||||
import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsDay;
|
||||
import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsMonth;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
|
||||
/**
|
||||
@@ -129,11 +130,26 @@ public class DailyToMonthlyAggregationJob implements Job {
|
||||
qd.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
qd.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
qd.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
qd.avgRespTime.avg().castToNum(BigDecimal.class).as("avgRespTime"),
|
||||
Expressions.cases()
|
||||
.when(qd.successCnt.sum().gt(0))
|
||||
.then(qd.avgRespTime.multiply(qd.successCnt).sum()
|
||||
.divide(qd.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime"),
|
||||
qd.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
qd.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
qd.p50RespTime.avg().castToNum(BigDecimal.class).as("p50RespTime"),
|
||||
qd.p95RespTime.avg().castToNum(BigDecimal.class).as("p95RespTime")))
|
||||
Expressions.cases()
|
||||
.when(qd.successCnt.sum().gt(0))
|
||||
.then(qd.p50RespTime.multiply(qd.successCnt).sum()
|
||||
.divide(qd.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("p50RespTime"),
|
||||
Expressions.cases()
|
||||
.when(qd.successCnt.sum().gt(0))
|
||||
.then(qd.p95RespTime.multiply(qd.successCnt).sum()
|
||||
.divide(qd.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("p95RespTime")))
|
||||
.from(qd)
|
||||
.where(qd.statTime.goe(startDate)
|
||||
.and(qd.statTime.loe(endDate)))
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.eactive.eai.rms.data.entity.onl.kjb.statistics.ApiStatsHourService;
|
||||
import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsDay;
|
||||
import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsHour;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
|
||||
/**
|
||||
@@ -125,11 +126,26 @@ public class HourlyToDailyAggregationJob implements Job {
|
||||
qh.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
qh.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
qh.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
qh.avgRespTime.avg().castToNum(BigDecimal.class).as("avgRespTime"),
|
||||
Expressions.cases()
|
||||
.when(qh.successCnt.sum().gt(0))
|
||||
.then(qh.avgRespTime.multiply(qh.successCnt).sum()
|
||||
.divide(qh.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime"),
|
||||
qh.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
qh.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
qh.p50RespTime.avg().castToNum(BigDecimal.class).as("p50RespTime"),
|
||||
qh.p95RespTime.avg().castToNum(BigDecimal.class).as("p95RespTime")))
|
||||
Expressions.cases()
|
||||
.when(qh.successCnt.sum().gt(0))
|
||||
.then(qh.p50RespTime.multiply(qh.successCnt).sum()
|
||||
.divide(qh.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("p50RespTime"),
|
||||
Expressions.cases()
|
||||
.when(qh.successCnt.sum().gt(0))
|
||||
.then(qh.p95RespTime.multiply(qh.successCnt).sum()
|
||||
.divide(qh.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("p95RespTime")))
|
||||
.from(qh)
|
||||
.where(qh.statTime.goe(startDateTime)
|
||||
.and(qh.statTime.loe(endDateTime)))
|
||||
|
||||
+19
-3
@@ -23,6 +23,7 @@ import com.eactive.eai.rms.data.entity.onl.kjb.statistics.ApiStatsMonthService;
|
||||
import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsMonth;
|
||||
import com.eactive.eai.rms.data.entity.onl.kjb.statistics.QApiStatsYear;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
|
||||
/**
|
||||
@@ -127,11 +128,26 @@ public class MonthlyToYearlyAggregationJob implements Job {
|
||||
qm.seq900TimeoutCnt.sum().as("seq900TimeoutCnt"),
|
||||
qm.seq900SystemErrCnt.sum().as("seq900SystemErrCnt"),
|
||||
qm.seq900BizErrCnt.sum().as("seq900BizErrCnt"),
|
||||
qm.avgRespTime.avg().castToNum(BigDecimal.class).as("avgRespTime"),
|
||||
Expressions.cases()
|
||||
.when(qm.successCnt.sum().gt(0))
|
||||
.then(qm.avgRespTime.multiply(qm.successCnt).sum()
|
||||
.divide(qm.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("avgRespTime"),
|
||||
qm.minRespTime.min().castToNum(BigDecimal.class).as("minRespTime"),
|
||||
qm.maxRespTime.max().castToNum(BigDecimal.class).as("maxRespTime"),
|
||||
qm.p50RespTime.avg().castToNum(BigDecimal.class).as("p50RespTime"),
|
||||
qm.p95RespTime.avg().castToNum(BigDecimal.class).as("p95RespTime")))
|
||||
Expressions.cases()
|
||||
.when(qm.successCnt.sum().gt(0))
|
||||
.then(qm.p50RespTime.multiply(qm.successCnt).sum()
|
||||
.divide(qm.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("p50RespTime"),
|
||||
Expressions.cases()
|
||||
.when(qm.successCnt.sum().gt(0))
|
||||
.then(qm.p95RespTime.multiply(qm.successCnt).sum()
|
||||
.divide(qm.successCnt.sum()).castToNum(BigDecimal.class))
|
||||
.otherwise((BigDecimal) null)
|
||||
.as("p95RespTime")))
|
||||
.from(qm)
|
||||
.where(qm.statTime.goe(startMonth)
|
||||
.and(qm.statTime.loe(endMonth)))
|
||||
|
||||
Reference in New Issue
Block a user