비즈니스 로그 기준 히스토리 조정

assets DW 추가
경제지표 보유 API
게임로그 snapshot
s3 비즈니스 로그 추가
칼리움 dashboard api
This commit is contained in:
2025-08-04 17:38:30 +09:00
parent a834c7a004
commit b0a99ca55f
50 changed files with 1653 additions and 686 deletions

View File

@@ -12,7 +12,6 @@ import com.caliverse.admin.domain.response.IndicatorsResponse.NRU;
import com.caliverse.admin.domain.response.IndicatorsResponse.PU;
import com.caliverse.admin.domain.response.IndicatorsResponse.Playtime;
import com.caliverse.admin.domain.response.IndicatorsResponse.Retention;
import com.caliverse.admin.domain.response.IndicatorsResponse.Segment;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -37,13 +36,10 @@ public class IndicatorsResult {
//Retention
@JsonProperty("retention")
private List<Retention> retentionList;
//Segment
@JsonProperty("start_dt")
private String startDt;
@JsonProperty("end_dt")
private String endDt;
@JsonProperty("segment")
private List<Segment> segmentList;
//플레이타임
@JsonProperty("playtime")
private List<Playtime> playtimeList;

View File

@@ -0,0 +1,131 @@
package com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import com.caliverse.admin.Indicators.Indicatorsservice.base.IndicatorsLogLoadServiceBase;
import com.caliverse.admin.global.common.constants.AdminConstants;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class IndicatorsAssetsLoadService extends IndicatorsLogLoadServiceBase {
public IndicatorsAssetsLoadService(
@Qualifier("mongoIndicatorTemplate") MongoTemplate mongoTemplate
) {
super(mongoTemplate);
}
@Override
public <T extends IndicatorsLog> List<T> getIndicatorsLogData(String startTime, String endTime, Class<T> clazz) {
Criteria criteria = makeCriteria(startTime, endTime, "logDay");
GroupOperation groupOperation = Aggregation.group("logDay")
.sum("gold").as("gold")
.sum("sapphire").as("sapphire")
.sum("calium").as("calium")
.sum("ruby").as("ruby")
.sum("item_11570001").as("item_11570001")
.sum("item_11570002").as("item_11570002")
.sum("item_13080002").as("item_13080002")
.sum("item_13080004").as("item_13080004")
.sum("item_13080005").as("item_13080005")
.sum("item_13080006").as("item_13080006")
.sum("item_13080007").as("item_13080007")
.sum("item_13080008").as("item_13080008")
.sum("item_13080009").as("item_13080009")
.count().as("userCount");
ProjectionOperation projection = Aggregation.project()
.andExclude("_id")
.and("_id").as(AdminConstants.MONGO_DB_KEY_LOGDAY)
.and("gold").as("gold")
.and("sapphire").as("sapphire")
.and("calium").as("calium")
.and("ruby").as("ruby")
.and("item_11570001").as("item_11570001") //강화잉크
.and("item_11570002").as("item_11570002") //연성잉크
.and("item_13080002").as("item_13080002") //퀘스트 메달
.and("item_13080004").as("item_13080004") //보급품 메달
.and("item_13080005").as("item_13080005") //제작 메달
.and("item_13080006").as("item_13080006") //315 포드
.and("item_13080007").as("item_13080007") //316 포드
.and("item_13080008").as("item_13080008") //317 포드
.and("item_13080009").as("item_13080009") //318 포드
.and("userCount").as("userCount");
List<AggregationOperation> operations = List.of(
Aggregation.match(criteria),
groupOperation,
projection,
Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
return mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_ASSETS
, clazz
).getMappedResults();
}
public <T extends IndicatorsLog> List<T> getAssetsLogData(String startTime, String endTime, Class<T> clazz) {
Criteria criteria = makeCriteria(startTime, endTime, "logDay");
GroupOperation groupOperation = Aggregation.group("logDay")
.sum("gold").as("gold")
.sum("sapphire").as("sapphire")
.sum("calium").as("calium")
.sum("ruby").as("ruby")
.sum("item_11570001").as("item_11570001")
.sum("item_11570002").as("item_11570002")
.sum("item_13080002").as("item_13080002")
.sum("item_13080004").as("item_13080004")
.sum("item_13080005").as("item_13080005")
.sum("item_13080006").as("item_13080006")
.sum("item_13080007").as("item_13080007")
.sum("item_13080008").as("item_13080008")
.sum("item_13080009").as("item_13080009")
.count().as("userCount");
ProjectionOperation projection = Aggregation.project()
.andExclude("_id")
.and("logDay").as(AdminConstants.MONGO_DB_KEY_LOGDAY)
.and("gold").as("gold")
.and("sapphire").as("sapphire")
.and("calium").as("calium")
.and("ruby").as("ruby")
.and("item_11570001").as("item_11570001")
.and("item_11570002").as("item_11570002")
.and("item_13080002").as("item_13080002")
.and("item_13080004").as("item_13080004")
.and("item_13080005").as("item_13080005")
.and("item_13080006").as("item_13080006")
.and("item_13080007").as("item_13080007")
.and("item_13080008").as("item_13080008")
.and("item_13080009").as("item_13080009")
.and("userCount").as("userCount");
List<AggregationOperation> operations = List.of(
Aggregation.match(criteria),
groupOperation,
projection,
Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
return mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_ASSETS
, clazz
).getMappedResults();
}
}

View File

@@ -0,0 +1,90 @@
package com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import com.caliverse.admin.Indicators.Indicatorsservice.base.IndicatorsLogLoadServiceBase;
import com.caliverse.admin.global.common.constants.AdminConstants;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class IndicatorsCurrencyLoadService extends IndicatorsLogLoadServiceBase {
public IndicatorsCurrencyLoadService(
@Qualifier("mongoIndicatorTemplate") MongoTemplate mongoTemplate
) {
super(mongoTemplate);
}
@Override
public <T extends IndicatorsLog> List<T> getIndicatorsLogData(String startTime, String endTime, Class<T> clazz) {
return getCurrencyLogData(startTime, endTime, "Acquire", clazz);
}
public <T extends IndicatorsLog> List<T> getCurrencyLogData(String startTime, String endTime, String deltaType, Class<T> clazz) {
Criteria criteria = makeCriteria(startTime, endTime, "logDay");
UnwindOperation unwindOperation = Aggregation.unwind("currencies");
MatchOperation matchOp = Aggregation.match(
Criteria.where("currencies.amountDeltaType").is(deltaType)
);
AggregationOperation groupOp = context -> new Document("$group",
new Document("_id", new Document("logDay", "$logDay")
.append("currencyType", "$currencies.currencyType")
.append("action", "$currencies.action")
)
.append("actionAmount", new Document("$sum", "$currencies.deltaAmount"))
);
AggregationOperation groupOp2 = context -> new Document("$group",
new Document("_id", new Document("logDay", "$_id.logDay")
.append("currencyType", "$_id.currencyType")
)
.append("totalDeltaAmount", new Document("$sum", "$actionAmount"))
.append("actions", new Document("$push",
new Document("k", "$_id.action").append("v", "$actionAmount")
))
);
AddFieldsOperation addFieldsOp = Aggregation.addFields()
.addField("actionSummary")
.withValue(ArrayOperators.ArrayToObject.arrayToObject("$actions"))
.build();
AggregationOperation projectOp = context -> new Document("$project", new Document()
.append("_id", 0)
.append("logDay", "$_id.logDay")
.append("currencyType", "$_id.currencyType")
.append("totalDeltaAmount", 1)
.append("actionSummary", 1)
);
List<AggregationOperation> operations = List.of(
Aggregation.match(criteria),
unwindOperation,
matchOp,
groupOp,
groupOp2,
addFieldsOp,
projectOp,
Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
return mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_CURRENCY
, clazz
).getMappedResults();
}
}

View File

@@ -0,0 +1,95 @@
package com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import com.caliverse.admin.Indicators.Indicatorsservice.base.IndicatorsLogLoadServiceBase;
import com.caliverse.admin.global.common.constants.AdminConstants;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class IndicatorsItemLoadService extends IndicatorsLogLoadServiceBase {
public IndicatorsItemLoadService(
@Qualifier("mongoIndicatorTemplate") MongoTemplate mongoTemplate
) {
super(mongoTemplate);
}
@Override
public <T extends IndicatorsLog> List<T> getIndicatorsLogData(String startTime, String endTime, Class<T> clazz) {
return getItemsLogData(startTime, endTime, "Acquire", clazz);
}
public <T extends IndicatorsLog> List<T> getItemsLogData(String startTime, String endTime, String deltaType, Class<T> clazz) {
Criteria criteria = makeCriteria(startTime, endTime, "logDay");
UnwindOperation unwindOperation = Aggregation.unwind("itemDetails");
UnwindOperation unwindOperation2 = Aggregation.unwind("itemDetails.items");
MatchOperation matchOp = Aggregation.match(
Criteria.where("itemDetails.items.countDeltaType").is(deltaType)
);
AggregationOperation groupOp = context -> new Document("$group",
new Document("_id", new Document("logDay", "$logDay")
.append("itemMID", "$itemDetails.items.itemMID")
.append("action", "$itemDetails.items.action")
)
.append("actionCount", new Document("$sum", "$itemDetails.items.deltaCount"))
.append("itemName", new Document("$first", "$itemDetails.items.itemName"))
);
AggregationOperation groupOp2 = context -> new Document("$group",
new Document("_id", new Document("logDay", "$_id.logDay")
.append("itemMID", "$_id.itemMID")
)
.append("totalDeltaCount", new Document("$sum", "$actionCount"))
.append("itemName", new Document("$first", "$itemName"))
.append("actions", new Document("$push",
new Document("k", "$_id.action").append("v", "$actionCount")
))
);
AddFieldsOperation addFieldsOp = Aggregation.addFields()
.addField("actionSummary")
.withValue(ArrayOperators.ArrayToObject.arrayToObject("$actions"))
.build();
AggregationOperation projectOp = context -> new Document("$project", new Document()
.append("_id", 0)
.append("logDay", "$_id.logDay")
.append("itemId", "$_id.itemMID")
.append("itemName", 1)
.append("totalDeltaCount", 1)
.append("actionSummary", 1)
);
List<AggregationOperation> operations = List.of(
Aggregation.match(criteria),
unwindOperation,
unwindOperation2,
matchOp,
groupOp,
groupOp2,
addFieldsOp,
projectOp,
Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
return mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_ITEM
, clazz
).getMappedResults();
}
}

View File

@@ -0,0 +1,28 @@
package com.caliverse.admin.Indicators.entity;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.Indexed;
@Getter
@Setter
public class AssetsIndicatorInfo implements IndicatorsLog {
@Indexed
private String logDay;
private Double gold;
private Double sapphire;
private Double calium;
private Double ruby;
private Integer item_11570001;
private Integer item_11570002;
private Integer item_13080002;
private Integer item_13080004;
private Integer item_13080005;
private Integer item_13080006;
private Integer item_13080007;
private Integer item_13080008;
private Integer item_13080009;
private Integer userCount;
}

View File

@@ -0,0 +1,19 @@
package com.caliverse.admin.Indicators.entity;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.Indexed;
import java.util.Map;
@Getter
@Setter
public class CurrencyIndicatorInfo implements IndicatorsLog {
@Indexed
private String logDay;
private Double totalDeltaAmount;
private Map<String, Double> actionSummary;
private String currencyType;
}

View File

@@ -0,0 +1,20 @@
package com.caliverse.admin.Indicators.entity;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.Indexed;
import java.util.Map;
@Getter
@Setter
public class ItemIndicatorInfo implements IndicatorsLog {
@Indexed
private String logDay;
private Long totalDeltaCount;
private Map<String, Double> actionSummary;
private String itemId;
private String itemName;
}

View File

@@ -0,0 +1,83 @@
package com.caliverse.admin.Indicators.entity;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
@Getter
@Setter
@Document(collection = "assets")
@CompoundIndexes({
@CompoundIndex(name = "logDay_userGuid_idx", def = "{'logDay': 1, 'userGuid': 1}", background = true),
@CompoundIndex(name = "logDay_idx", def = "{'logDay': 1}", background = true)
})
public class SnapshotLogInfo extends LogInfoBase{
@Indexed
private String logDay;
private String accountId;
@Indexed
private String userGuid;
private String userNickname;
private Double gold;
private Double sapphire;
private Double calium;
private Double ruby;
private Integer item_11570001;
private Integer item_11570002;
private Integer item_13080002;
private Integer item_13080004;
private Integer item_13080005;
private Integer item_13080006;
private Integer item_13080007;
private Integer item_13080008;
private Integer item_13080009;
private LocalDateTime lastLogoutTime;
public SnapshotLogInfo(String logDay,
String accountId,
String userGuid,
String userNickname,
Double gold,
Double sapphire,
Double calium,
Double ruby,
Integer item_11570001,
Integer item_11570002,
Integer item_13080002,
Integer item_13080004,
Integer item_13080005,
Integer item_13080006,
Integer item_13080007,
Integer item_13080008,
Integer item_13080009,
LocalDateTime lastLogoutTime
) {
super(StatisticsType.SNAPSHOT);
this.logDay = logDay;
this.accountId = accountId;
this.userGuid = userGuid;
this.userNickname = userNickname;
this.gold = gold;
this.sapphire = sapphire;
this.calium = calium;
this.ruby = ruby;
this.item_11570001 = item_11570001;
this.item_11570002 = item_11570002;
this.item_13080002 = item_13080002;
this.item_13080004 = item_13080004;
this.item_13080005 = item_13080005;
this.item_13080006 = item_13080006;
this.item_13080007 = item_13080007;
this.item_13080008 = item_13080008;
this.item_13080009 = item_13080009;
this.lastLogoutTime = lastLogoutTime;
}
}

View File

@@ -18,7 +18,8 @@ public enum StatisticsType {
USER_CREATE,
USER_LOGIN,
CURRENCY,
ITEM
ITEM,
SNAPSHOT
;
public static StatisticsType getStatisticsType(String type) {

View File

@@ -4,4 +4,5 @@ import com.caliverse.admin.Indicators.entity.CurrencyLogInfo;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface IndicatorCurrencyRepository extends MongoRepository<CurrencyLogInfo, String> {
boolean existsByLogDayAndUserGuid(String logDay, String userGuid);
}

View File

@@ -4,4 +4,5 @@ import com.caliverse.admin.Indicators.entity.ItemLogInfo;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface IndicatorItemRepository extends MongoRepository<ItemLogInfo, String> {
boolean existsByLogDayAndUserGuid(String logDay, String userGuid);
}

View File

@@ -0,0 +1,8 @@
package com.caliverse.admin.Indicators.indicatorrepository;
import com.caliverse.admin.Indicators.entity.SnapshotLogInfo;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface IndicatorSnapshotRepository extends MongoRepository<SnapshotLogInfo, String> {
boolean existsByLogDayAndUserGuid(String logDay, String userGuid);
}

View File

@@ -4,4 +4,5 @@ import com.caliverse.admin.Indicators.entity.UserCreateLogInfo;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface IndicatorUserCreateRepository extends MongoRepository<UserCreateLogInfo, String> {
boolean existsByLogDayAndUserGuid(String logDay, String userGuid);
}

View File

@@ -4,4 +4,5 @@ import com.caliverse.admin.Indicators.entity.UserLoginLogInfo;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface IndicatorUserLoginRepository extends MongoRepository<UserLoginLogInfo, String> {
boolean existsByLogDayAndUserGuid(String logDay, String userGuid);
}

View File

@@ -49,65 +49,33 @@ public class IndicatorsController {
@RequestParam Map<String, String> requestParams,HttpServletResponse res){
indicatorsService.retentionExcelDown(requestParams,res);
}
//Segment
@GetMapping("/segment/list")
public ResponseEntity<IndicatorsResponse> segmentList(
@GetMapping("/currency/list")
public ResponseEntity<IndicatorsResponse> currencyList(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.segmentList(requestParams));
}
@GetMapping("/segment/excel-down")
public void segmentExcelDown(
@RequestParam Map<String, String> requestParams,HttpServletResponse res){
indicatorsService.segmentExcelDown(requestParams, res);
}
//Playtime
@GetMapping("/playtime/list")
public ResponseEntity<IndicatorsResponse> playTimeList(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.playTimeList(requestParams));
}
@GetMapping("/playtime/excel-down")
public void playTimeExcelDown(
@RequestParam Map<String, String> requestParams,HttpServletResponse res){
indicatorsService.playTimeExcelDown(requestParams, res);
return ResponseEntity.ok().body( indicatorsService.currencyList(requestParams));
}
// 재화 지표
@GetMapping("/currency/use")
public ResponseEntity<IndicatorsResponse> acquire(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.getCurrencyUse(requestParams));
}
@GetMapping("/currency/excel-down")
public void currencyExcelDown(
@RequestParam Map<String, String> requestParams, HttpServletResponse res){
indicatorsService.currencyExcelDown(requestParams, res);
}
// VBP 지표
@GetMapping("/currency/vbp")
public ResponseEntity<IndicatorsResponse> vbp(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.getVBPList(requestParams));
}
// Item 지표
@GetMapping("/currency/item")
@GetMapping("/item/list")
public ResponseEntity<IndicatorsResponse> item(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.getItemList(requestParams));
}
// 보유 지표
@GetMapping("/assets/list")
public ResponseEntity<IndicatorsResponse> assets(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.getAssetsList(requestParams));
}
// 인스턴스 지표
@GetMapping("/currency/instance")
public ResponseEntity<IndicatorsResponse> instance(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.getInstanceList(requestParams));
}
// 의상/타투 지표
@GetMapping("/currency/clothes")
public ResponseEntity<IndicatorsResponse> clothes(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( indicatorsService.getClothesList(requestParams));
}
// DAU 지표
@GetMapping("/dau/list")
@@ -122,7 +90,10 @@ public class IndicatorsController {
indicatorsService.dauExcelDown(requestParams, res);
}
@GetMapping("/dashboard/calium/converter")
public ResponseEntity<IndicatorsResponse> dashboardCaliumConverter(){
return ResponseEntity.ok().body( indicatorsService.getCaliumConverter());
}
/*
// DAU 지표
@GetMapping("/daily-medal/list")

View File

@@ -108,4 +108,16 @@ public class LogController {
@RequestBody LogGameRequest logGameRequest){
logService.userLoginExcelExport(response, logGameRequest);
}
@GetMapping("/user/snapshot/list")
public ResponseEntity<LogResponse> snapshotList(
@RequestParam Map<String, String> requestParams){
return ResponseEntity.ok().body( logService.getSnapshotLogList(requestParams));
}
@PostMapping("/user/snapshot/excel-export")
public void userSnapshotExcelExport(HttpServletResponse response,
@RequestBody LogGameRequest logGameRequest){
logService.SnapshotExcelExport(response, logGameRequest);
}
}

View File

@@ -33,12 +33,6 @@ public enum LogAction {
SCHEDULE_BATTLE_EVENT,
SCHEDULE_LAND_AUCTION,
// 파일
COMPRESS,
EXTRACT,
BACKUP,
RESTORE,
BANNER,
BATTLE_EVENT,
BUILDING,

View File

@@ -2,20 +2,12 @@ package com.caliverse.admin.domain.entity.log;
public enum LogCategory {
SCHEDULER,
MAIL,
NOTICE,
DYNAMODB,
MARIADB,
MESSAGE_QUEUE,
REDIS,
S3,
USER_MANAGEMENT,
EXTERNAL_API,
BATCH_JOB,
AUTHENTICATION,
AUTHORIZATION,
FILE_PROCESSING,
VALIDATION,
DATA_INIT,
;
}

View File

@@ -2,6 +2,8 @@ package com.caliverse.admin.domain.request;
import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.SEARCHTYPE;
import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.entity.log.LogCategory;
import com.caliverse.admin.mongodb.entity.DBType;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@@ -20,6 +22,9 @@ public class HistoryRequest {
private String userMail;
@JsonProperty("db_type")
private DBType dbType;
private LogCategory category;
private LogAction action;
private String status;
@JsonProperty("search_type")
private SEARCHTYPE searchType;

View File

@@ -1,6 +1,7 @@
package com.caliverse.admin.domain.response;
import com.caliverse.admin.domain.entity.Log;
import com.caliverse.admin.mongodb.domain.BusinessLog;
import com.caliverse.admin.mongodb.domain.HistoryLogInfoBase;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -30,7 +31,8 @@ public class HistoryResponse {
@JsonProperty("list")
// private List<Log> list ;
private List<HistoryLogInfoBase> list ;
// private List<HistoryLogInfoBase> list ;
private List<BusinessLog> list ;
private String content; // db에 text유형의 데이터를 가져옴

View File

@@ -1,6 +1,9 @@
package com.caliverse.admin.domain.response;
import com.caliverse.admin.Indicators.entity.AssetsIndicatorInfo;
import com.caliverse.admin.Indicators.entity.CurrencyIndicatorInfo;
import com.caliverse.admin.Indicators.entity.DauLogInfo;
import com.caliverse.admin.Indicators.entity.ItemIndicatorInfo;
import com.caliverse.admin.domain.entity.Currencys;
import com.caliverse.admin.domain.entity.Distinct;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -21,9 +24,10 @@ public class IndicatorsResponse {
private int status;
private String result;
@JsonProperty("data")
@JsonProperty("data")
private ResultData resultData;
@Data
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
@@ -32,6 +36,8 @@ public class IndicatorsResponse {
private String message;
private Dashboard dashboard;
@JsonProperty("dashboard_calium")
private DashboardCaliumConverter dashboardCalium;
@JsonProperty("user_statistics_list")
private List<userStatistics> userStatisticsList;
@JsonProperty("dau_list")
@@ -41,13 +47,17 @@ public class IndicatorsResponse {
//Retention
@JsonProperty("retention")
private List<Retention> retentionList;
@JsonProperty("currency_list")
private List<CurrencyIndicatorInfo> currencyList;
@JsonProperty("item_list")
private List<ItemIndicatorInfo> itemList;
@JsonProperty("assets_list")
private List<AssetsIndicatorInfo> assetsList;
//Segment
@JsonProperty("start_dt")
private String startDt;
@JsonProperty("end_dt")
private String endDt;
@JsonProperty("segment")
private List<Segment> segmentList;
//플레이타임
@JsonProperty("playtime")
private List<Playtime> playtimeList;
@@ -57,9 +67,6 @@ public class IndicatorsResponse {
@JsonProperty("list")
private List<DailyGoods> dailyGoods;
// @JsonProperty("dau_list")
// private List<DailyActiveUser> dailyActiveUserList;
}
@Data
@@ -72,6 +79,21 @@ public class IndicatorsResponse {
private MCU mcu;
}
@Data
@Builder
public static class DashboardCaliumConverter{
@JsonProperty("total_calium")
private Double totalCalium;
@JsonProperty("cumulative_calium")
private Double CumulativeCalium;
@JsonProperty("daily_fill_up_calium")
private Double dailyFillUpCalium;
@JsonProperty("converter_rate")
private Double converterRate;
@JsonProperty("inflation_rate")
private Double inflationRete;
}
//이용자 지표
@Data
@Builder
@@ -129,19 +151,6 @@ public class IndicatorsResponse {
}
@Data
@Builder
public static class Dday{
private String date;
private String dif;
}
@Data
@Builder
public static class Segment{
private String type;
private String au;
private String dif;
}
@Data
@Builder
public static class Playtime{
private LocalDate date;
@JsonProperty("user_cnt")

View File

@@ -47,6 +47,8 @@ public class LogResponse {
private List<ItemDetailLogInfo> itemDetailList;
@JsonProperty("currency_item_list")
private List<CurrencyItemLogInfo> currencyItemList;
@JsonProperty("snapshot_list")
private List<SnapshotLogInfo> snapshotList;
private int total;
@JsonProperty("total_all")

View File

@@ -10,6 +10,7 @@ import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.common.utils.DateUtils;
import com.caliverse.admin.mongodb.domain.BusinessLog;
import com.caliverse.admin.mongodb.domain.HistoryLogInfoBase;
import com.caliverse.admin.mongodb.service.HistoryLogService;
import lombok.RequiredArgsConstructor;
@@ -36,14 +37,10 @@ public class HistoryService {
requestParams = CommonUtils.pageSetting(requestParams);
String searchType = requestParams.get("searchType").toString();
String searchData = requestParams.get("searchData").toString();
HISTORYTYPEDETAIL historyType = requestParams.get("historyType").equals("") ? null : HISTORYTYPEDETAIL.valueOf(requestParams.get("historyType").toString());
LocalDateTime startDt = requestParams.get("startDate").equals("") ? null : DateUtils.stringISOToLocalDateTime(requestParams.get("startDate").toString());
LocalDateTime endDt = requestParams.get("endDate").equals("") ? null : DateUtils.stringISOToLocalDateTime(requestParams.get("endDate").toString());
// List<Log> historyList = historyMapper.getHistoryList(requestParams);
HistoryRequest historyRequest = new HistoryRequest();
historyRequest.setHistoryType(historyType);
historyRequest.setStartDt(startDt);
historyRequest.setEndDt(endDt);
if(searchType.equals("NAME")){
@@ -63,11 +60,11 @@ public class HistoryService {
historyRequest.setUserMail(searchData);
}
List<HistoryLogInfoBase> historyList = historyLogService.loadHistoryData(historyRequest, HistoryLogInfoBase.class);
List<BusinessLog> logList = historyLogService.loadHistoryData(historyRequest, BusinessLog.class);
return HistoryResponse.builder()
.resultData(HistoryResponse.ResultData.builder()
.list(historyList)
.list(logList)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
@@ -76,11 +73,11 @@ public class HistoryService {
public HistoryResponse getHistory(HistoryRequest historyRequest){
List<HistoryLogInfoBase> historyList = historyLogService.loadHistoryData(historyRequest, HistoryLogInfoBase.class);
List<BusinessLog> logList = historyLogService.loadHistoryData(historyRequest, BusinessLog.class);
return HistoryResponse.builder()
.resultData(HistoryResponse.ResultData.builder()
.list(historyList)
.list(logList)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())

View File

@@ -1,6 +1,5 @@
package com.caliverse.admin.domain.service;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
@@ -8,22 +7,20 @@ import java.util.stream.Collectors;
import com.caliverse.admin.Indicators.Indicatorsservice.aggregationservice.*;
import com.caliverse.admin.Indicators.entity.*;
import com.caliverse.admin.domain.response.LogResponse;
import com.caliverse.admin.domain.datacomponent.MetaDataHandler;
import com.caliverse.admin.dynamodb.domain.atrrib.CaliumStorageAttrib;
import com.caliverse.admin.dynamodb.service.DynamodbCaliumService;
import com.caliverse.admin.global.common.utils.DateUtils;
import com.caliverse.admin.logs.logservice.indicators.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.caliverse.admin.domain.entity.Currencys;
import com.caliverse.admin.domain.entity.ROUTE;
import com.caliverse.admin.domain.response.IndicatorsResponse;
import com.caliverse.admin.global.common.code.CommonCode;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.exception.RestApiException;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.common.utils.ExcelUtils;
@@ -35,7 +32,7 @@ import lombok.RequiredArgsConstructor;
@Slf4j
public class IndicatorsService {
private final ExcelUtils excelUtils;
private final MetaDataHandler metaDataHandler;
private IndicatorsAuLoadService indicatorsAuLoadService;
private final IndicatorsDauLoadService indicatorsDauLoadService;
@@ -49,12 +46,16 @@ public class IndicatorsService {
private final IndicatorsUgqCreateLoadService indicatorsUgqCreateLoadService;
private final IndicatorsMetaverServerLoadService indicatorsMetaverServerLoadService;
private final IndicatorsRetentionLoadService indicatorsRetentionLoadService;
private final IndicatorsCurrencyLoadService indicatorsCurrencyLoadService;
private final IndicatorsItemLoadService indicatorsItemLoadService;
private final IndicatorsAssetsLoadService indicatorsAssetsLoadService;
private final IndicatorsDauService dauService;
private final IndicatorsNruService indicatorsNruService;
private final IndicatorsMcuService mcuService;
private final DynamoDBMetricsService dynamoDBMetricsService;
private final DynamodbCaliumService dynamodbCaliumService;
//UserStatistics
public IndicatorsResponse list(Map<String, String> requestParams){
@@ -138,6 +139,30 @@ public class IndicatorsService {
.build();
}
public IndicatorsResponse getCaliumConverter(){
CaliumStorageAttrib storage = dynamodbCaliumService.getCaliumConverter();
CaliumStorageAttrib.CaliumConverterStorage caliumConverterStorage = storage.getCaliumConverterStorage();
CaliumStorageAttrib.CaliumExchangerStorage caliumExchangerStorage = storage.getCaliumExchangerStorage();
IndicatorsResponse.DashboardCaliumConverter dashboard = IndicatorsResponse.DashboardCaliumConverter.builder()
.converterRate(caliumConverterStorage.getConverterDailyConvertRate())
.CumulativeCalium(caliumConverterStorage.getConverterCumulativeCalium())
.totalCalium(caliumConverterStorage.getConverterTotalCalium())
.dailyFillUpCalium(caliumConverterStorage.getConverterDailyFillUpStandardCalium())
.inflationRete(caliumExchangerStorage.getExchangerDailyInflationRate())
.build();
return IndicatorsResponse.builder()
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.resultData(IndicatorsResponse.ResultData.builder()
.dashboardCalium(dashboard)
.build()
)
.build();
}
//유저 지표 엑셀 다운로드(현재 frontend 기능으로 사용)
public void userExcelDown(Map<String, String> requestParams, HttpServletResponse res){
@@ -168,6 +193,7 @@ public class IndicatorsService {
// }
}
// 유저 지표 Retention
public IndicatorsResponse retentionList(Map<String, String> requestParams){
LocalDateTime startDt = DateUtils.stringISOToLocalDateTime(requestParams.get("start_dt"));
@@ -198,144 +224,81 @@ public class IndicatorsService {
.build();
}
public void retentionExcelDown(Map<String, String> requestParams,HttpServletResponse res){
List<IndicatorsResponse.Retention> retentionList = new ArrayList<>();
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
// int cnt = dateRange.size();
// for (LocalDate date : dateRange) {
// List<IndicatorsResponse.Dday> dDayList = new ArrayList<>();
// for (int i = 0; i < cnt; i++){
// IndicatorsResponse.Dday dDay = IndicatorsResponse.Dday.builder()
// .date("D+" + i)
// .dif("0%")
// .build();
// dDayList.add(dDay);
// }
// cnt -- ;
// IndicatorsResponse.Retention retention = IndicatorsResponse.Retention.builder()
// .date(date)
// .dDay(dDayList)
// .build();
// retentionList.add(retention);
// }
// // 엑셀 파일 생성 및 다운로드
// try {
// ExcelUtils.exportToExcelByRentention(retentionList,res);
// }catch (IOException exception){
// throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.getMessage());
// }
}
// 유저 지표 Retention
public IndicatorsResponse segmentList(Map<String, String> requestParams){
// LocalDate searchDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("search_dt")));
// List<IndicatorsResponse.Segment> segmentList = Arrays.asList(
// IndicatorsResponse.Segment.builder().type("Excellent").au("0").dif("0%").build(),
// IndicatorsResponse.Segment.builder().type("Influential").au("0").dif("0%").build(),
// IndicatorsResponse.Segment.builder().type("Potential").au("0").dif("0%").build(),
// IndicatorsResponse.Segment.builder().type("Before leave").au("0").dif("0%").build(),
// IndicatorsResponse.Segment.builder().type("InActive").au("0").dif("0%").build(),
// IndicatorsResponse.Segment.builder().type("New Join").au("0").dif("0%").build()
// );
// return IndicatorsResponse.builder()
// .resultData(IndicatorsResponse.ResultData.builder()
// .segmentList(segmentList)
// .startDt(searchDt.minusDays(100))
// .endDt(searchDt)
// .build())
// .status(CommonCode.SUCCESS.getHttpStatus())
// .result(CommonCode.SUCCESS.getResult())
// .build();
return null;
public IndicatorsResponse currencyList(Map<String, String> requestParams){
LocalDateTime startDt = DateUtils.stringISOToLocalDateTime(requestParams.get("start_dt"));
LocalDateTime endDt = DateUtils.stringISOToLocalDateTime(requestParams.get("end_dt"));
String currencyType = CommonUtils.objectToString(requestParams.get("currency_type"));
String deltaType = CommonUtils.objectToString(requestParams.get("delta_type"));
List<CurrencyIndicatorInfo> currencyList = indicatorsCurrencyLoadService.getCurrencyLogData(
startDt.toString().substring(0, 10),
endDt.toString().substring(0, 10),
deltaType,
CurrencyIndicatorInfo.class);
}
public void segmentExcelDown(Map<String, String> requestParams, HttpServletResponse res){
LocalDate searchDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("search_dt")));
currencyList = currencyList.stream().filter(data -> data.getCurrencyType().equals(currencyType)).toList();
List<IndicatorsResponse.Segment> segmentList = Arrays.asList(
IndicatorsResponse.Segment.builder().type("Excellent").au("0").dif("0%").build(),
IndicatorsResponse.Segment.builder().type("Influential").au("0").dif("0%").build(),
IndicatorsResponse.Segment.builder().type("Potential").au("0").dif("0%").build(),
IndicatorsResponse.Segment.builder().type("Before leave").au("0").dif("0%").build(),
IndicatorsResponse.Segment.builder().type("InActive").au("0").dif("0%").build(),
IndicatorsResponse.Segment.builder().type("New Join").au("0").dif("0%").build()
);
LocalDate startDt = searchDt.minusDays(100);
LocalDate endDt = searchDt;
// 엑셀 파일 생성 및 다운로드
try {
ExcelUtils.exportToExcelBySegment(segmentList,startDt,endDt,res);
}catch (IOException exception){
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.getMessage());
}
}
// 유저 지표 플레이타임
public IndicatorsResponse playTimeList(Map<String, String> requestParams){
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
List<IndicatorsResponse.Playtime> playtimeList = new ArrayList<>();
for (LocalDate date : dateRange){
IndicatorsResponse.Playtime build = IndicatorsResponse.Playtime.builder()
.date(date)
.totalTime(0)
.averageTime(0)
.userCnt(Arrays.asList(0, 0, 0, 0))
.build();
playtimeList.add(build);
}
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.playtimeList(playtimeList)
.currencyList(currencyList)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
public void playTimeExcelDown(Map<String, String> requestParams, HttpServletResponse res){
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
List<IndicatorsResponse.Playtime> playtimeList = new ArrayList<>();
for (LocalDate date : dateRange){
IndicatorsResponse.Playtime build = IndicatorsResponse.Playtime.builder()
.date(date)
.totalTime(0)
.averageTime(0)
.userCnt(Arrays.asList(0, 0, 0, 0))
.build();
playtimeList.add(build);
}
String sheetName = "PlayTime";
//이이템 지표
public IndicatorsResponse getItemList(Map<String, String> requestParams){
LocalDateTime startDt = DateUtils.stringISOToLocalDateTime(requestParams.get("start_dt"));
LocalDateTime endDt = DateUtils.stringISOToLocalDateTime(requestParams.get("end_dt"));
String itemId = CommonUtils.objectToString(requestParams.get("item_id"));
String deltaType = CommonUtils.objectToString(requestParams.get("delta_type"));
List<ItemIndicatorInfo> itemList = indicatorsItemLoadService.getItemsLogData(
startDt.toString().substring(0, 10),
endDt.toString().substring(0, 10),
deltaType,
ItemIndicatorInfo.class);
String headerNames[] = new String[]{"일자","30분 이내","30분~1시간", "1시간~3시간", "3시간 이상"
, "총 누적 플레이타임(분)","1인당 평균 플레이타임(분)"};
itemList = itemList.stream()
.filter(data -> data.getItemId().equals(itemId))
.peek(data -> data.setItemName(metaDataHandler.getTextStringData(data.getItemName())))
.toList();
String[][] bodyDatass = new String[playtimeList.size()][7];
for (int i = 0; i < playtimeList.size(); i++) {
IndicatorsResponse.Playtime entry = playtimeList.get(i);
bodyDatass[i][0] = String.valueOf(entry.getDate());
bodyDatass[i][1] = String.valueOf(entry.getUserCnt().get(0));
bodyDatass[i][2] = String.valueOf(entry.getUserCnt().get(1));
bodyDatass[i][3] = String.valueOf(entry.getUserCnt().get(2));
bodyDatass[i][4] = String.valueOf(entry.getUserCnt().get(3));
bodyDatass[i][5] = String.valueOf(entry.getTotalTime());
bodyDatass[i][6] = String.valueOf(entry.getAverageTime());
}
String outfileName = "PlayTime_"+ LocalDateTime.now().getNano();
// 엑셀 파일 생성 및 다운로드
try {
excelUtils.excelDownload(sheetName,headerNames,bodyDatass,outfileName,res);
}catch (IOException exception){
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.getMessage());
}
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.itemList(itemList)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
//보유 지표
public IndicatorsResponse getAssetsList(Map<String, String> requestParams){
LocalDateTime startDt = DateUtils.stringISOToLocalDateTime(requestParams.get("start_dt"));
LocalDateTime endDt = DateUtils.stringISOToLocalDateTime(requestParams.get("end_dt"));
List<AssetsIndicatorInfo> assetsList = indicatorsAssetsLoadService.getIndicatorsLogData(
startDt.toString().substring(0, 10),
endDt.toString().substring(0, 10),
AssetsIndicatorInfo.class);
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.assetsList(assetsList)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
@@ -463,101 +426,7 @@ public class IndicatorsService {
.collect(Collectors.toList());
return resList;
}
//재화 지표
public IndicatorsResponse getCurrencyUse(Map<String, String> requestParams) {
LocalDate startDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("start_dt")));
LocalDate endDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("end_dt")));
String currencyType = CommonUtils.objectToString(requestParams.get("currency_type"));
List<Currencys> dailyList = getCurrencyCount(startDt, endDt, currencyType);
List<Currencys> totalList = getDailyGoodsTotal(startDt, endDt, currencyType);
List<IndicatorsResponse.DailyGoods> dailyGoodsList = getDailyGoodsList(currencyType, dailyList, totalList);
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.dailyGoods(dailyGoodsList)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
//재화 지표 엑셀 다운로드
public void currencyExcelDown(Map<String, String> requestParams, HttpServletResponse res){
LocalDate startDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("start_dt")));
LocalDate endDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("end_dt")));
String currencyType = CommonUtils.objectToString(requestParams.get("currency_type"));
List<Currencys> dailyList = getCurrencyCount(startDt, endDt, currencyType);
List<Currencys> totalList = getDailyGoodsTotal(startDt, endDt, currencyType);
List<IndicatorsResponse.DailyGoods> dailyGoodsList = getDailyGoodsList(currencyType, dailyList, totalList);
// 엑셀 파일 생성 및 다운로드
try {
ExcelUtils.exportToExcelByDailyGoods(dailyGoodsList, res);
}catch (IOException exception){
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.getMessage());
}
}
//VBP 지표
public IndicatorsResponse getVBPList(Map<String, String> requestParams){
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
List<Currencys> dailyGoods = new ArrayList<>();
for (LocalDate date : dateRange){
List<Currencys> currencysList = Arrays.asList(
Currencys.builder().route("OFFLINE_VISIT").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("OFFLINE_PAYMENT").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("ONLINE_VISIT").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("ONLINE_PAYMENT").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("STORE").deltaType("USE").date(date).count(0).build(),
Currencys.builder().route("VBP").deltaType("USE").date(date).count(0).build()
);
dailyGoods.addAll(currencysList);
}
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.currencysList(dailyGoods)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
//이이템 지표
public IndicatorsResponse getItemList(Map<String, String> requestParams){
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
List<Currencys> dailyGoods = new ArrayList<>();
for (LocalDate date : dateRange){
List<Currencys> currencysList = Arrays.asList(
Currencys.builder().route("Dummy_GET_1").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("Dummy_GET_2").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("Dummy_GET_3").deltaType("GET").date(date).count(0).build(),
Currencys.builder().route("Dummy_USE_1").deltaType("USE").date(date).count(0).build(),
Currencys.builder().route("Dummy_USE_2").deltaType("USE").date(date).count(0).build(),
Currencys.builder().route("Dummy_USE_3").deltaType("USE").date(date).count(0).build()
);
dailyGoods.addAll(currencysList);
}
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.currencysList(dailyGoods)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
//인스턴스 지표
public IndicatorsResponse getInstanceList(Map<String, String> requestParams){
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
@@ -582,30 +451,6 @@ public class IndicatorsService {
}
//의상/타투 지표
public IndicatorsResponse getClothesList(Map<String, String> requestParams){
String startDt = CommonUtils.objectToString(requestParams.get("start_dt"));
String endDt = CommonUtils.objectToString(requestParams.get("end_dt"));
List<LocalDate> dateRange = CommonUtils.dateRange(startDt, endDt);
List<Currencys> dailyGoods = new ArrayList<>();
for (LocalDate date : dateRange){
List<Currencys> currencysList = Arrays.asList(
Currencys.builder().route("Dummy_Item_Id_1").date(date).count(0).build(),
Currencys.builder().route("Dummy_Item_Id_2").date(date).count(0).build()
);
dailyGoods.addAll(currencysList);
}
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.currencysList(dailyGoods)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
//DAU 지표
public IndicatorsResponse getDauDataList(Map<String, String> requestParams){
@@ -691,64 +536,6 @@ public class IndicatorsService {
}
/*
//Daily Medal 지표
public IndicatorsResponse getDailyMedalDataList(Map<String, String> requestParams){
LocalDate startDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("start_dt")));
LocalDate endDt = LocalDate.parse(CommonUtils.objectToString(requestParams.get("end_dt")));
List<DailyMedal> dailyMedal = getDailyMedal(startDt, endDt);
return IndicatorsResponse.builder()
.resultData(IndicatorsResponse.ResultData.builder()
.dailyMedalList(dailyMedal)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
public List<DailyMedal> getDailyMedal(LocalDate startTime, LocalDate endTime){
Map map = new HashMap();
map.put("startDt" , CommonUtils.startOfDay(startTime));
map.put("endDt" , CommonUtils.endOfDay(endTime));
List<DailyMedal> dateActive = indicatorsMapper.getDailyMedal(map);
// 결과를 처리하여 결과값 반환
return dateActive;
}
*/
public List<Object> getDauList(LocalDate startTime, LocalDate endTime){
Map map = new HashMap();
map.put("startDt" , CommonUtils.startOfDay(startTime));
map.put("endDt" , CommonUtils.endOfDay(endTime));
//List<DailyActiveUser> dateActive = indicatorsMapper.getDailyActiveUserList(map);
// 결과를 처리하여 결과값 반환
return null;
}
public List<DauLogInfo> getActiveUserCount(LocalDate startTime, String endTime){
//Map map = new HashMap();
//map.put("startDt" , CommonUtils.startOfDay(startTime));
//map.put("endDt" , CommonUtils.endOfDay(endTime));
//List<Distinct> dateActive = indicatorsMapper.getDailyActive(map);
// 결과를 처리하여 결과값 반환
List<DauLogInfo> ativeUsers = indicatorsAuLoadService.getIndicatorsLogData(endTime, endTime, DauLogInfo.class);
return ativeUsers;
}
public List<Currencys> getCurrencyCount(LocalDate startTime, LocalDate endTime, String type){
Map inputMap = new HashMap();

View File

@@ -16,10 +16,7 @@ import com.caliverse.admin.global.common.utils.DateUtils;
import com.caliverse.admin.global.component.tracker.ExcelProgressTracker;
import com.caliverse.admin.logs.Indicatordomain.GenericMongoLog;
import com.caliverse.admin.logs.logservice.businesslogservice.BusinessLogGenericService;
import com.caliverse.admin.logs.logservice.indicators.IndicatorsCurrencyService;
import com.caliverse.admin.logs.logservice.indicators.IndicatorsItemService;
import com.caliverse.admin.logs.logservice.indicators.IndicatorsUserCreateService;
import com.caliverse.admin.logs.logservice.indicators.IndicatorsUserLoginService;
import com.caliverse.admin.logs.logservice.indicators.*;
import com.caliverse.admin.mongodb.dto.MongoPageResult;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
@@ -50,6 +47,7 @@ public class LogService {
private final IndicatorsItemService indicatorsItemService;
private final IndicatorsUserLoginService indicatorsUserLoginService;
private final IndicatorsUserCreateService indicatorsUserCreateService;
private final IndicatorsSnapshotService indicatorsSnapshotService;
public LogResponse genericLogList(LogGenericRequest logGenericRequest){
int page = logGenericRequest.getPageNo();
@@ -924,4 +922,93 @@ public class LogService {
}
public LogResponse getSnapshotLogList(Map<String, String> requestParams){
String searchType = requestParams.get("search_type");
String searchData = requestParams.get("search_data");
LocalDateTime startDt = DateUtils.stringISOToLocalDateTime(requestParams.get("start_dt"));
LocalDateTime endDt = DateUtils.stringISOToLocalDateTime(requestParams.get("end_dt"));
String orderBy = requestParams.get("orderby");
int pageNo = Integer.parseInt(requestParams.get("page_no"));
int pageSize = Integer.parseInt(requestParams.get("page_size"));
MongoPageResult<SnapshotLogInfo> result = indicatorsSnapshotService.getSnapshotLogData(
searchType,
searchData,
startDt.toString().substring(0, 10),
endDt.toString().substring(0, 10),
orderBy,
pageNo,
pageSize,
SnapshotLogInfo.class
);
int totalCount = result.getTotalCount();
return LogResponse.builder()
.resultData(LogResponse.ResultData.builder()
.snapshotList(result.getItems())
.total(result.getItems().size())
.totalAll(totalCount)
.pageNo(pageNo)
.build())
.status(CommonCode.SUCCESS.getHttpStatus())
.result(CommonCode.SUCCESS.getResult())
.build();
}
public void SnapshotExcelExport(HttpServletResponse response, LogGameRequest logGameRequest){
String taskId = logGameRequest.getTaskId();
LocalDateTime startDt = logGameRequest.getStartDt().plusHours(9);
LocalDateTime endDt = logGameRequest.getEndDt().plusHours(9).plusDays(1);
logGameRequest.setStartDt(startDt);
logGameRequest.setEndDt(endDt);
logGameRequest.setPageNo(null);
logGameRequest.setPageSize(null);
progressTracker.updateProgress(taskId, 5, 100, "엑셀 생성 준비 중...");
MongoPageResult<SnapshotLogInfo> result = null;
try{
result = indicatorsSnapshotService.getSnapshotLogData(
logGameRequest.getSearchType().toString(),
logGameRequest.getSearchData(),
startDt.toString().substring(0, 10),
endDt.toString().substring(0, 10),
logGameRequest.getOrderBy(),
logGameRequest.getPageNo(),
logGameRequest.getPageSize(),
SnapshotLogInfo.class
);
progressTracker.updateProgress(taskId, 20, 100, "데이터 생성완료");
}catch(UncategorizedMongoDbException e){
if (e.getMessage().contains("Sort exceeded memory limit")) {
log.error("MongoDB Query memory limit error: {}", e.getMessage());
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_LOG_MEMORY_LIMIT.toString());
} else if (e.getMessage().contains("time limit")) {
log.error("MongoDB Query operation exceeded time limit: {}", e.getMessage());
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_LOG_MEMORY_LIMIT.toString());
}else {
log.error("MongoDB Query error", e);
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_MONGODB_QUERY.toString());
}
}catch (Exception e){
log.error("SnapshotExcelExport ExcelExport Data Search Error", e);
}
List<SnapshotLogInfo> logList = result.getItems();
progressTracker.updateProgress(taskId, 30, 100, "데이터 파싱 완료...");
try{
excelService.generateExcelToResponse(
response,
logList,
"유저 스냅샷 로그 데이터",
"sheet1",
taskId
);
}catch (Exception e){
log.error("SnapshotExcelExport Excel Export Create Error", e);
throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ERROR_EXCEL_DOWN.toString());
}
}
}

View File

@@ -324,7 +324,7 @@ public class MenuService {
dynamodbMenuService.deleteBanner(banner.getId().intValue());
//운영DB 데이터 추가됐다고 게임서버 알림
//게임서버 알림
notifyGameServers("deleteBanner", null);
return MenuResponse.builder()

View File

@@ -1,6 +1,9 @@
package com.caliverse.admin.domain.service;
import com.caliverse.admin.domain.entity.log.LogStatus;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.common.utils.FileUtils;
import com.caliverse.admin.mongodb.service.BusinessLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,6 +29,9 @@ public class S3Service {
@Autowired(required = false)
private final S3Client s3Client;
private final BusinessLogService businessLogService;
private final FileUtils fileUtils;
@Value("${amazon.s3.bucket-name}")
private String bucketName;
@@ -73,6 +79,19 @@ public class S3Service {
RequestBody.fromBytes(Files.readAllBytes(file.toPath()))
);
if(response.sdkHttpResponse().isSuccessful()){
businessLogService.logS3(
LogStatus.SUCCESS,
"",
CommonUtils.getAdmin().getId().toString(),
CommonUtils.getClientIp(),
bucketName,
objectKey,
file.length(),
fileUtils.getContentType(file.getName())
);
}
return cloudFrontUrl + objectKey;
}catch (S3Exception | IOException e) {
throw e;

View File

@@ -76,27 +76,32 @@ public class CaliumStorageAttrib {
private Double converterDailyFillUpStandardCalium;
private String converterLastFillUpDate;
private Double converterTotalCalium;
//누적 총량
@DynamoDbAttribute("converter_cumulative_calium")
public Double getConverterCumulativeCalium() {
return converterCumulativeCalium;
}
//컨버터 칼리움 전환 비율
@DynamoDbAttribute("converter_daily_convert_rate")
public Double getConverterDailyConvertRate() {
return converterDailyConvertRate;
}
//daily 누적 칼리움 수
@DynamoDbAttribute("converter_daily_fill_up_standard_calium")
public Double getConverterDailyFillUpStandardCalium() {
return converterDailyFillUpStandardCalium;
}
//마지막 누적 시간
@DynamoDbAttribute("converter_last_fill_up_date")
public String getConverterLastFillUpDate() {
return converterLastFillUpDate;
}
//잔여 수량
@DynamoDbAttribute("converter_total_calium")
public Double getConverterTotalCalium() {
return converterTotalCalium;
@@ -109,10 +114,11 @@ public class CaliumStorageAttrib {
@DynamoDbBean
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class CaliumExchangerStorage {
private Integer exchangerDailyInflationRate;
private Double exchangerDailyInflationRate;
//인플레이션 가중치
@DynamoDbAttribute("exchanger_daily_inflation_rate")
public Integer getExchangerDailyInflationRate() {
public Double getExchangerDailyInflationRate() {
return exchangerDailyInflationRate;
}
}
@@ -126,17 +132,20 @@ public class CaliumStorageAttrib {
private Double operatorTotalCalium;
private Double operatorCalium;
private String operatorCaliumFillUpDate;
//운영용 사용 가능량
@DynamoDbAttribute("operator_calium")
public Double getOperatorCalium() {
return operatorCalium;
}
//운영용 승인 누적 날짜
@DynamoDbAttribute("operator_calium_fill_up_date")
public String getOperatorCaliumFillUpDate() {
return operatorCaliumFillUpDate;
}
//운영 승인 누적량
@DynamoDbAttribute("operator_total_calium")
public Double getOperatorTotalCalium() {
return operatorTotalCalium;

View File

@@ -1,9 +1,11 @@
package com.caliverse.admin.dynamodb.repository;
import com.caliverse.admin.dynamodb.domain.atrrib.CaliumStorageAttrib;
import com.caliverse.admin.dynamodb.domain.doc.CaliumStorageDoc;
public interface CaliumStorageRepository extends DynamoDBRepository<CaliumStorageDoc> {
double getTotal();
CaliumStorageAttrib getStorage();
void updateTotal(double caliumCnt);
void stockDeduction(double caliumCnt);
}

View File

@@ -1,7 +1,9 @@
package com.caliverse.admin.dynamodb.repository.Impl;
import com.caliverse.admin.dynamodb.domain.atrrib.CaliumStorageAttrib;
import com.caliverse.admin.dynamodb.domain.atrrib.LandAuctionActivityAttrib;
import com.caliverse.admin.dynamodb.domain.doc.CaliumStorageDoc;
import com.caliverse.admin.dynamodb.domain.doc.LandAuctionActivityDoc;
import com.caliverse.admin.dynamodb.repository.BaseDynamoDBRepository;
import com.caliverse.admin.dynamodb.repository.CaliumStorageRepository;
import com.caliverse.admin.dynamodb.service.DynamoDBOperations;
@@ -44,6 +46,19 @@ public class CaliumStorageRepositoryImpl extends BaseDynamoDBRepository<CaliumSt
return total;
}
@Override
public CaliumStorageAttrib getStorage() {
Key key = Key.builder()
.partitionValue(DynamoDBConstants.PK_KEY_CALIUM)
.sortValue(DynamoDBConstants.EMPTY)
.build();
CaliumStorageDoc doc = findById(key);
if(doc == null) return null;
return doc.getAttribValue();
}
@Override
public void updateTotal(double caliumCnt) {
try{

View File

@@ -1,5 +1,6 @@
package com.caliverse.admin.dynamodb.service;
import com.caliverse.admin.dynamodb.domain.atrrib.CaliumStorageAttrib;
import com.caliverse.admin.global.common.annotation.DynamoDBTransaction;
import com.caliverse.admin.dynamodb.repository.CaliumStorageRepository;
import lombok.RequiredArgsConstructor;
@@ -16,6 +17,11 @@ public class DynamodbCaliumService {
return caliumStorageRepository.getTotal();
}
public CaliumStorageAttrib getCaliumConverter(){
return caliumStorageRepository.getStorage();
}
@DynamoDBTransaction
public void updateCaliumTotal(double caliumCnt){
caliumStorageRepository.updateTotal(caliumCnt);

View File

@@ -20,6 +20,8 @@ public class AdminConstants {
public static final String MONGO_DB_COLLECTION_ITEM = "item";
public static final String MONGO_DB_COLLECTION_CREATE = "userCreate";
public static final String MONGO_DB_COLLECTION_LOGIN = "userLogin";
public static final String MONGO_DB_COLLECTION_ASSETS = "assets";
public static final String MONGO_DB_COLLECTION_BUSINESS_LOG = "businessLog";
public static final String MONGO_DB_KEY_LOGTIME = "logTime";
public static final String MONGO_DB_KEY_LOGMONTH = "logMonth";
@@ -47,6 +49,9 @@ public class AdminConstants {
public static final String MONGO_DB_KEY_IP = "ip";
public static final String MONGO_DB_KEY_HISTORY_TYPE = "historyType";
public static final String MONGO_DB_KEY_USER_ID = "userId";
public static final String MONGO_DB_KEY_WORKER = "worker";
public static final String MONGO_DB_KEY_CATEGORY = "category";
public static final String MONGO_DB_KEY_STATUS = "status";
public static final String MONGO_DB_KEY_USER_GUID_LIST = "userGuidList";
public static final String MONGO_DB_KEY_USER_GUID_LIST_COUNT = "userGuidListCount";
@@ -61,6 +66,7 @@ public class AdminConstants {
public static final String REGEX_MSG_LOGIN_TO_USER_AUTH = "\"Action\":\"LoginToUserAuth\"";
public static final String REGEX_MSG_LOGIN_TO_GAME = "\"Action\":\"LoginToGame\"";
public static final String REGEX_MSG_USER_LOGOUT = "\"Action\":\"UserLogout\"";
public static final String REGEX_MSG_USER_LOGOUT_SNAPSHOT = "\"Action\":\"UserLogoutSnapShot\"";
public static final String REGEX_MSG_CHARACTER_CREATE = "\"Action\":\"CharacterCreate\"";
public static final String REGEX_MSG_PLAY_TIME = "\"Action\":\"UserLogout\"";
public static final String REGEX_MSG_UGQ_CREATE = "\"Action\":\"UgqApiQuestCraete\"";

View File

@@ -400,234 +400,5 @@ public class ExcelUtils {
return input.length() == 32;
}
//재화 지표 엑셀 다운 샘플
public static void exportToExcelByDailyGoods(List<IndicatorsResponse.DailyGoods> dailyGoodsList
,HttpServletResponse res) throws IOException {
ServletOutputStream servletOutputStream = res.getOutputStream();
try (Workbook workbook = new XSSFWorkbook()) {
// 엑셀 시트 생성
Sheet sheet = workbook.createSheet("DailyGoodsData");
// 첫 번째 라인 - 일자
Row dateRow = sheet.createRow(0);
dateRow.createCell(0).setCellValue("일자");
sheet.autoSizeColumn(0);
sheet.setColumnWidth((0), (sheet.getColumnWidth(0))+1024*2); //너비 더 넓게
for (int i = 0; i < dailyGoodsList.size(); i++) {
dateRow.createCell((i+1) + 1).setCellValue(dailyGoodsList.get(i).getDate().toString());
//sheet 넓이 auto
sheet.autoSizeColumn((i+2));
}
// 두 번째 라인 - ACQUIRE 총량
Row acquireRow = sheet.createRow(1);
acquireRow.createCell(0).setCellValue("(Total)생산량");
for (int i = 0; i < dailyGoodsList.size(); i++) {
List<IndicatorsResponse.Total> totals = dailyGoodsList.get(i).getTotal();
for (int j = 0; j < totals.size(); j++) {
if ("ACQUIRE".equals(totals.get(j).getDeltaType())) {
acquireRow.createCell((i+1) + 1).setCellValue(totals.get(j).getQuantity());
}
}
}
// 세번째 라인 - CONSUME 총량
Row consumeRow = sheet.createRow(2);
consumeRow.createCell(0).setCellValue("(Total)소진량");
for (int i = 0; i < dailyGoodsList.size(); i++) {
List<IndicatorsResponse.Total> totals = dailyGoodsList.get(i).getTotal();
for (int j = 0; j < totals.size(); j++) {
if ("CONSUME".equals(totals.get(j).getDeltaType())) {
consumeRow.createCell((i+1) + 1).setCellValue(totals.get(j).getQuantity());
}
}
}
// 나머지 라인 - Route 별 quantity
List<ROUTE> acquireRoutes = Arrays.asList(
ROUTE.QUEST_REWARD, ROUTE.SEASON_PASS, ROUTE.FROM_PROP,
ROUTE.CLAIM_REWARD, ROUTE.USE_ITEM, ROUTE.TATTOO_ENHANCE,
ROUTE.TATTOO_CONVERSION, ROUTE.SHOP_BUY, ROUTE.SHOP_SELL,
ROUTE.PAID_PRODUCT, ROUTE.TRADE_ADD, ROUTE.NFT_LOCKIN
);
int rowIndex = 3; // 시작 행 인덱스
for (ROUTE route : acquireRoutes) {
Row routeRow = sheet.createRow(rowIndex++);
routeRow.createCell(0).setCellValue("GET");
routeRow.createCell(1).setCellValue(route.getDescription());
for (int i = 0; i < dailyGoodsList.size(); i++) {
List<IndicatorsResponse.DailyData> dailyDataList = dailyGoodsList.get(i).getDailyData();
for (IndicatorsResponse.DailyData dailyData : dailyDataList) {
if(dailyData.getDeltaType().equals("ACQUIRE")){
List<Currencys> data = dailyData.getData();
for (Currencys currencys : data) {
if (route.getDescription().equals(currencys.getRoute())) {
routeRow.createCell((i+1) + 1).setCellValue(currencys.getQuantity());
}
}
}
}
}
}
List<ROUTE> consumeRoutes = Arrays.asList(
ROUTE.SHOP_BUY, ROUTE.SHOP_SELL, ROUTE.USE_PROP,
ROUTE.USE_TAXI, ROUTE.TATTOO_ENHANCE, ROUTE.TATTOO_CONVERSION,
ROUTE.SHOUT, ROUTE.SUMMON, ROUTE.CREATE_PARTYROOM,
ROUTE.INVENTORY_EXPAND, ROUTE.TRADE_REMOVE, ROUTE.NFT_UNLOCK
);
for (ROUTE route : consumeRoutes) {
Row routeRow = sheet.createRow(rowIndex++);
routeRow.createCell(0).setCellValue("USE");
routeRow.createCell(1).setCellValue(route.getDescription());
for (int i = 0; i < dailyGoodsList.size(); i++) {
List<IndicatorsResponse.DailyData> dailyDataList = dailyGoodsList.get(i).getDailyData();
for (IndicatorsResponse.DailyData dailyData : dailyDataList) {
if(dailyData.getDeltaType().equals("CONSUME")){
List<Currencys> data = dailyData.getData();
for (Currencys currencys : data) {
if (route.getDescription().equals(currencys.getRoute())) {
routeRow.createCell((i+1) + 1).setCellValue(currencys.getQuantity());
}
}
}
}
}
}
//cell 머지
sheet.addMergedRegion(CellRangeAddress.valueOf("A1:B1"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A2:B2"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A3:B3"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A4:A15"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A16:A27"));
/**
* download
*/
res.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
res.setHeader("Content-Disposition", "attachment;filename=DailyGoodsData_" + LocalDateTime.now().getNano()
+ ".xlsx");
workbook.write(servletOutputStream);
workbook.close();
servletOutputStream.flush();
servletOutputStream.close();
} catch (IOException e) {
log.error("exportToExcelByDailyGoods IOException: {}", e.getMessage());
}
}
//유저 지표 Retention 엑셀 다운 샘플
public static void exportToExcelByRentention(List<IndicatorsResponse.Retention> list
,HttpServletResponse res) throws IOException {
ServletOutputStream servletOutputStream = res.getOutputStream();
try (Workbook workbook = new XSSFWorkbook()) {
// 엑셀 시트 생성
Sheet sheet = workbook.createSheet("Retention");
// 첫 번째 라인 - 일자
Row dateRow = sheet.createRow(0);
dateRow.createCell(0).setCellValue("국가");
dateRow.createCell(1).setCellValue("일자");
dateRow.createCell(2).setCellValue("NRU");
for (int i = 1; i < list.size(); i++) {
dateRow.createCell(i+2).setCellValue("D+"+i);
//sheet 넓이 auto
sheet.autoSizeColumn(i+2);
}
int rowIndex = 1; // 시작 행 인덱스
// 두 번째 라인
// for (IndicatorsResponse.Retention retention : list){
// Row row = sheet.createRow(rowIndex++);
// row.createCell(0).setCellValue("ALL");
// List<IndicatorsResponse.Dday> dDay = retention.getDDay();
// row.createCell(1).setCellValue(retention.getDate().toString());
// for (int j = 0; j < dDay.size(); j++) {
// row.createCell(j+2).setCellValue(dDay.get(j).getDif());
// }
//
// }
//cell 머지
sheet.addMergedRegion(CellRangeAddress.valueOf("A2:A"+(list.size()+1)));
/*sheet.addMergedRegion(CellRangeAddress.valueOf("A1:B1"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A2:B2"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A3:B3"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A4:A15"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A16:A27"));*/
/**
* download
*/
res.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
res.setHeader("Content-Disposition", "attachment;filename=Retention_" + LocalDateTime.now().getNano()
+ ".xlsx");
workbook.write(servletOutputStream);
workbook.close();
servletOutputStream.flush();
servletOutputStream.close();
} catch (IOException e) {
log.error("exportToExcelByRentention IOException: {}", e.getMessage());
}
}
//유저 지표 Retention 엑셀 다운 샘플
public static void exportToExcelBySegment(List<IndicatorsResponse.Segment> list,LocalDate startDt,
LocalDate endDt,HttpServletResponse res) throws IOException {
ServletOutputStream servletOutputStream = res.getOutputStream();
try (Workbook workbook = new XSSFWorkbook()) {
// 엑셀 시트 생성
Sheet sheet = workbook.createSheet("Segment");
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
sheet.autoSizeColumn(2);
sheet.addMergedRegion(CellRangeAddress.valueOf("B1:C1"));
sheet.setColumnWidth(0,sheet.getColumnWidth(0)+1024*4);
int rowIndex = 0;
// 첫 번째 라인 - 일자
Row headerRow = sheet.createRow(rowIndex++);
headerRow.createCell(0).setCellValue(startDt.toString()+"~"+endDt.toString());
headerRow.createCell(1).setCellValue("KIP");
Row subHeaderRow = sheet.createRow(rowIndex++);
subHeaderRow.createCell(0).setCellValue("세그먼트 분류");
subHeaderRow.createCell(1).setCellValue("AU");
subHeaderRow.createCell(2).setCellValue("AU Percentage by User Segment (%)");
Row dataRow = null;
for (int i = 0; i < list.size(); i++) {
dataRow = sheet.createRow(i+rowIndex);
dataRow.createCell(0).setCellValue(list.get(i).getType());
dataRow.createCell(1).setCellValue(list.get(i).getAu());
dataRow.createCell(2).setCellValue(list.get(i).getDif());
}
//cell 머지
/*sheet.addMergedRegion(CellRangeAddress.valueOf("A1:B1"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A2:B2"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A3:B3"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A4:A15"));
sheet.addMergedRegion(CellRangeAddress.valueOf("A16:A27"));*/
/**
* download
*/
res.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
res.setHeader("Content-Disposition", "attachment;filename=Segment_" + LocalDateTime.now().getNano()
+ ".xlsx");
workbook.write(servletOutputStream);
workbook.close();
servletOutputStream.flush();
servletOutputStream.close();
} catch (IOException e) {
log.error("exportToExcelBySegment IOException: {}", e.getMessage());
}
}
}

View File

@@ -123,8 +123,8 @@ public class MysqlLoggingInterceptor implements Interceptor {
if (sqlId.contains("BlackList")) return MysqlConstants.TABLE_NAME_USER_BLOCK;
if (sqlId.contains("Calium")) return MysqlConstants.TABLE_NAME_CALIUM_REQUEST;
if (sqlId.contains("Data")) return MysqlConstants.TABLE_NAME_DATA_INIT;
if (sqlId.contains("Event")) return MysqlConstants.TABLE_NAME_EVENT;
if (sqlId.contains("Battle")) return MysqlConstants.TABLE_NAME_BATTLE_EVENT;
if (sqlId.contains("Event")) return MysqlConstants.TABLE_NAME_EVENT;
if (sqlId.contains("GroupAuth")) return MysqlConstants.TABLE_NAME_GROUP_AUTH;
if (sqlId.contains("Group")) return MysqlConstants.TABLE_NAME_GROUP;
if (sqlId.contains("Mail")) return MysqlConstants.TABLE_NAME_MAIL;

View File

@@ -0,0 +1,28 @@
package com.caliverse.admin.logs.Indicatordomain;
import com.caliverse.admin.global.common.constants.AdminConstants;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
@Document(collection = AdminConstants.MONGO_DB_COLLECTION_LOG)
@Getter
@Setter
public class SnapshotMongoLog extends MongoLogSearchBase{
private Double gold;
private Double sapphire;
private Double calium;
private Double ruby;
private Integer item_11570001;
private Integer item_11570002;
private Integer item_13080002;
private Integer item_13080004;
private Integer item_13080005;
private Integer item_13080006;
private Integer item_13080007;
private Integer item_13080008;
private Integer item_13080009;
private LocalDateTime lastLogoutTime;
}

View File

@@ -0,0 +1,481 @@
package com.caliverse.admin.logs.logservice.businesslogservice;
import com.caliverse.admin.global.common.constants.AdminConstants;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
@Slf4j
@Service
public class BusinessLogSnapshotService extends BusinessLogServiceBase {
public BusinessLogSnapshotService(@Qualifier("mongoBusinessLogTemplate") MongoTemplate mongoTemplate) {
super(mongoTemplate);
}
public <T> List<T> loadBusinessLogData(String startTime, String endTime, Class<T> class1) {
Criteria criteria = makeCriteria(startTime, endTime);
List<AggregationOperation> operations = setDefaultOperation(criteria);
operations.add(context ->
new Document("$addFields",
new Document("gold",
new Document("$toDouble",
new Document("$arrayElemAt", Arrays.asList(
new Document("$ifNull", Arrays.asList(
new Document("$getField",
new Document("field", "captures")
.append("input",
new Document("$regexFind",
new Document("input", "$message")
.append("regex", "\"Gold\":([0-9.]+)")
)
)
),
Arrays.asList()
)),
0
))
)
)
.append("sapphire",
new Document("$toDouble",
new Document("$arrayElemAt", Arrays.asList(
new Document("$ifNull", Arrays.asList(
new Document("$getField",
new Document("field", "captures")
.append("input",
new Document("$regexFind",
new Document("input", "$message")
.append("regex", "\"Sapphire\":([0-9.]+)")
)
)
),
Arrays.asList()
)),
0
))
)
)
.append("calium",
new Document("$toDouble",
new Document("$arrayElemAt", Arrays.asList(
new Document("$ifNull", Arrays.asList(
new Document("$getField",
new Document("field", "captures")
.append("input",
new Document("$regexFind",
new Document("input", "$message")
.append("regex", "\"Calium\":([0-9.]+)")
)
)
),
Arrays.asList()
)),
0
))
)
)
.append("ruby",
new Document("$toDouble",
new Document("$arrayElemAt", Arrays.asList(
new Document("$ifNull", Arrays.asList(
new Document("$getField",
new Document("field", "captures")
.append("input",
new Document("$regexFind",
new Document("input", "$message")
.append("regex", "\"Ruby\":([0-9.]+)")
)
)
),
Arrays.asList()
)),
0
))
)
)
.append("itemsString",
new Document("$regexFind",
new Document("input", "$message")
.append("regex", "\"items\":\\s*(\\[.*?\\])")
.append("options", "s")
)
)
.append("snapshotDatetime",
new Document("$switch",
new Document("branches", Arrays.asList(
new Document("case",
new Document("$eq", Arrays.asList(
new Document("$type", "$logTime"),
"date"
))
).append("then", "$logTime"),
new Document("case",
new Document("$eq", Arrays.asList(
new Document("$type", "$logTime"),
"string"
))
).append("then",
new Document("$dateFromString",
new Document("dateString", "$logTime")
.append("onError", "$NOW")
)
)
))
.append("default", "$NOW")
)
)
)
);
operations.add(context ->
new Document("$addFields",
new Document("items",
new Document("$cond",
new Document("if",
new Document("$ne", Arrays.asList("$itemsString", null))
)
.append("then",
new Document("$map",
new Document("input",
new Document("$split", Arrays.asList(
new Document("$arrayElemAt", Arrays.asList("$itemsString.captures", 0)),
"},{"
))
)
.append("as", "item")
.append("in",
new Document("$let",
new Document("vars",
new Document("cleanItem",
new Document("$replaceAll",
new Document("input",
new Document("$replaceAll",
new Document("input",
new Document("$replaceAll",
new Document("input", "$$item")
.append("find", "[")
.append("replacement", "")
)
)
.append("find", "]")
.append("replacement", "")
)
)
.append("find", "{")
.append("replacement", "")
)
)
)
.append("in",
new Document("$let",
new Document("vars",
new Document("itemParts",
new Document("$split", Arrays.asList("$$cleanItem", ","))
)
)
.append("in",
new Document("ItemMetaId",
new Document("$toInt",
new Document("$trim",
new Document("input",
new Document("$arrayElemAt", Arrays.asList(
new Document("$split", Arrays.asList(
new Document("$arrayElemAt", Arrays.asList("$$itemParts", 0)),
":"
)),
1
))
)
)
)
)
.append("ItemStackCount",
new Document("$toInt",
new Document("$trim",
new Document("input",
new Document("$replaceAll",
new Document("input",
new Document("$arrayElemAt", Arrays.asList(
new Document("$split", Arrays.asList(
new Document("$arrayElemAt", Arrays.asList("$$itemParts", 1)),
":"
)),
1
))
)
.append("find", "}")
.append("replacement", "")
)
)
)
)
)
)
)
)
)
)
)
)
.append("else", Arrays.asList())
)
)
)
);
operations.add(context ->
new Document("$sort",
new Document("userGuid", 1)
.append("logTime", -1)
)
);
operations.add(context ->
new Document("$group",
new Document("_id",
new Document("userGuid", "$userGuid")
.append("date", "$logDay")
)
.append(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID, new Document("$first", "$accountId"))
.append(AdminConstants.MONGO_DB_KEY_USER_GUID, new Document("$first", "$userGuid"))
.append(AdminConstants.MONGO_DB_KEY_USER_NICKNAME, new Document("$first", "$userNickname"))
.append("gold", new Document("$first", "$gold"))
.append("sapphire", new Document("$first", "$sapphire"))
.append("calium", new Document("$first", "$calium"))
.append("ruby", new Document("$first", "$ruby"))
.append("items", new Document("$first", "$items"))
.append("snapshotDatetime", new Document("$first", "$snapshotDatetime"))
)
);
operations.add(context ->
new Document("$project",
new Document("_id", 0)
.append(AdminConstants.MONGO_DB_KEY_USER_GUID, "$userGuid")
.append(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID, "$accountId")
.append(AdminConstants.MONGO_DB_KEY_USER_NICKNAME, "$userNickname")
.append("gold", new Document("$ifNull", Arrays.asList("$gold", 0)))
.append("sapphire", new Document("$ifNull", Arrays.asList("$sapphire", 0)))
.append("calium", new Document("$ifNull", Arrays.asList("$calium", 0)))
.append("ruby", new Document("$ifNull", Arrays.asList("$ruby", 0)))
// .append("items", "$items")
.append("item_11570001",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 11570001))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_11570002",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 11570002))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080002",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080002))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080004",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080004))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080005",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080005))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080006",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080006))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080007",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080007))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080008",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080008))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("item_13080009",
new Document("$let",
new Document("vars",
new Document("foundItem",
new Document("$arrayElemAt", Arrays.asList(
new Document("$filter",
new Document("input", "$items")
.append("cond",
new Document("$eq", Arrays.asList("$$this.ItemMetaId", 13080009))
)
),
0
))
)
)
.append("in",
new Document("$ifNull", Arrays.asList("$$foundItem.ItemStackCount", 0))
)
)
)
.append("lastLogoutTime", "$snapshotDatetime")
)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
log.info("loadBusinessLogData Snapshot Query: {}", aggregation);
AggregationResults<T> results = getMongoTemplate().aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_LOG
, class1
);
return results.getMappedResults();
}
protected Criteria makeCriteria(String startTime, String endTime) {
return new Criteria()
.andOperator(
Criteria.where(AdminConstants.MONGO_DB_KEY_LOGTIME).gte(startTime)
,Criteria.where(AdminConstants.MONGO_DB_KEY_LOGTIME).lt(endTime)
, new Criteria()
.orOperator(
Criteria.where(AdminConstants.MONGO_DB_KEY_MESSAGE).regex(AdminConstants.REGEX_MSG_USER_LOGOUT_SNAPSHOT)
)
);
}
}

View File

@@ -86,6 +86,15 @@ public class IndicatorsCurrencyService extends IndicatorsLogLoadServiceBase {
if (indicatorsLog instanceof CurrencyLogInfo logInfo) {
try {
boolean exists = indicatorCurrencyRepository.existsByLogDayAndUserGuid(
logInfo.getLogDay(),
logInfo.getUserGuid()
);
if (exists) {
log.debug("Duplicate data skipped - logDay: {}, userGuid: {}",
logInfo.getLogDay(), logInfo.getUserGuid());
return;
}
indicatorCurrencyRepository.save(logInfo);
} catch (Exception e) {
log.error("Error Repository Write CurrencyLogInfo: {}, Message: {}", logInfo, e.getMessage());

View File

@@ -68,6 +68,15 @@ public class IndicatorsItemService extends IndicatorsLogLoadServiceBase {
if (indicatorsLog instanceof ItemLogInfo logInfo) {
try {
boolean exists = indicatorItemRepository.existsByLogDayAndUserGuid(
logInfo.getLogDay(),
logInfo.getUserGuid()
);
if (exists) {
log.debug("Duplicate data skipped - logDay: {}, userGuid: {}",
logInfo.getLogDay(), logInfo.getUserGuid());
return;
}
indicatorItemRepository.save(logInfo);
} catch (Exception e) {
log.error("Error Repository Write ItemLogInfo: {}, Message: {}", logInfo, e.getMessage());

View File

@@ -0,0 +1,222 @@
package com.caliverse.admin.logs.logservice.indicators;
import com.caliverse.admin.Indicators.Indicatordomain.IndicatorsLog;
import com.caliverse.admin.Indicators.Indicatorsservice.base.IndicatorsLogLoadServiceBase;
import com.caliverse.admin.Indicators.entity.SnapshotLogInfo;
import com.caliverse.admin.Indicators.indicatorrepository.IndicatorSnapshotRepository;
import com.caliverse.admin.global.common.constants.AdminConstants;
import com.caliverse.admin.logs.Indicatordomain.SnapshotMongoLog;
import com.caliverse.admin.logs.logservice.businesslogservice.BusinessLogSnapshotService;
import com.caliverse.admin.mongodb.dto.MongoPageResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class IndicatorsSnapshotService extends IndicatorsLogLoadServiceBase {
@Autowired private IndicatorSnapshotRepository indicatorSnapshotRepository;
@Autowired private BusinessLogSnapshotService snapshotService;
public IndicatorsSnapshotService(@Qualifier("mongoIndicatorTemplate") MongoTemplate mongoTemplate) {
super(mongoTemplate);
}
public void collectSnapshot(String startTime, String endTime){
String logTimeStr = startTime.substring(0, 10);
List<SnapshotMongoLog> indicatorsLog = null;
indicatorsLog = snapshotService.loadBusinessLogData("2024-08-28", endTime, SnapshotMongoLog.class);
if (indicatorsLog == null || indicatorsLog.isEmpty()) {
log.info("collectSnapshot indicatorsLog Log logDay: {} null", logTimeStr);
return;
}
for(SnapshotMongoLog mongo_log : indicatorsLog){
SnapshotLogInfo snapshotLog = new SnapshotLogInfo(logTimeStr,
mongo_log.getAccountId(),
mongo_log.getUserGuid(),
mongo_log.getUserNickname(),
mongo_log.getGold(),
mongo_log.getSapphire(),
mongo_log.getCalium(),
mongo_log.getRuby(),
mongo_log.getItem_11570001(),
mongo_log.getItem_11570002(),
mongo_log.getItem_13080002(),
mongo_log.getItem_13080004(),
mongo_log.getItem_13080005(),
mongo_log.getItem_13080006(),
mongo_log.getItem_13080007(),
mongo_log.getItem_13080008(),
mongo_log.getItem_13080009(),
mongo_log.getLastLogoutTime()
);
log.info("collectSnapshot Snapshot Log Save logDay: {}, info: {}", logTimeStr, snapshotLog);
saveStatLogData(snapshotLog);
}
}
private void saveStatLogData(IndicatorsLog indicatorsLog) {
if (indicatorsLog instanceof SnapshotLogInfo logInfo) {
try {
boolean exists = indicatorSnapshotRepository.existsByLogDayAndUserGuid(
logInfo.getLogDay(),
logInfo.getUserGuid()
);
if (exists) {
log.debug("Duplicate data skipped - logDay: {}, userGuid: {}",
logInfo.getLogDay(), logInfo.getUserGuid());
return;
}
indicatorSnapshotRepository.save(logInfo);
} catch (Exception e) {
log.error("Error Repository Write SnapshotLogInfo: {}, Message: {}", logInfo, e.getMessage());
}
} else {
log.error("Not instanceof SnapshotLogInfo");
}
}
@Override
public <T extends IndicatorsLog> List<T> getIndicatorsLogData(String startTime, String endTime, Class<T> clazz) {
Criteria criteria = makeCriteria(startTime, endTime, AdminConstants.MONGO_DB_KEY_LOGDAY);
ProjectionOperation projection = Aggregation.project()
.andExclude("_id")
.and(AdminConstants.MONGO_DB_KEY_LOGDAY).as(AdminConstants.MONGO_DB_KEY_LOGDAY)
.and(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID).as(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID)
.and(AdminConstants.MONGO_DB_KEY_USER_GUID).as(AdminConstants.MONGO_DB_KEY_USER_GUID)
.and(AdminConstants.MONGO_DB_KEY_USER_NICKNAME).as(AdminConstants.MONGO_DB_KEY_USER_NICKNAME)
.and("sapphire").as("sapphire")
.and("gold").as("gold")
.and("calium").as("calium")
.and("ruby").as("ruby")
.and("item_11570001").as("item_11570001")
.and("item_11570002").as("item_11570002")
.and("item_13080002").as("item_13080002")
.and("item_13080004").as("item_13080004")
.and("item_13080005").as("item_13080005")
.and("item_13080006").as("item_13080006")
.and("item_13080007").as("item_13080007")
.and("item_13080008").as("item_13080008")
.and("item_13080009").as("item_13080009")
.and("lastLogoutTime").as("lastLogoutTime");
List<AggregationOperation> operations = List.of(
Aggregation.match(criteria),
projection,
Aggregation.sort(Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
return mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build())
, AdminConstants.MONGO_DB_COLLECTION_ASSETS
, clazz
).getMappedResults();
}
public <T extends IndicatorsLog> MongoPageResult<T> getSnapshotLogData(
String searchType,
String searchData,
String startTime,
String endTime,
String orderBy,
Integer page,
Integer size,
Class<T> clazz
) {
Criteria criteria = makeCriteria(startTime, endTime, AdminConstants.MONGO_DB_KEY_LOGDAY);
if(searchData != null && !searchData.isEmpty()){
switch (searchType){
case "GUID":
criteria.and(AdminConstants.MONGO_DB_KEY_USER_GUID).is(searchData);
break;
case "NICKNAME":
criteria.and(AdminConstants.MONGO_DB_KEY_USER_NICKNAME).is(searchData);
break;
case "ACCOUNT":
criteria.and(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID).is(searchData);
break;
default:
log.error("searchType: {} not support", searchType);
return null;
}
}
ProjectionOperation projection = Aggregation.project()
.andExclude("_id")
.and(AdminConstants.MONGO_DB_KEY_LOGDAY).as(AdminConstants.MONGO_DB_KEY_LOGDAY)
.and(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID).as(AdminConstants.MONGO_DB_KEY_ACCOUNT_ID)
.and(AdminConstants.MONGO_DB_KEY_USER_GUID).as(AdminConstants.MONGO_DB_KEY_USER_GUID)
.and(AdminConstants.MONGO_DB_KEY_USER_NICKNAME).as(AdminConstants.MONGO_DB_KEY_USER_NICKNAME)
.and("sapphire").as("sapphire")
.and("gold").as("gold")
.and("calium").as("calium")
.and("ruby").as("ruby")
.and("item_11570001").as("item_11570001")
.and("item_11570002").as("item_11570002")
.and("item_13080002").as("item_13080002")
.and("item_13080004").as("item_13080004")
.and("item_13080005").as("item_13080005")
.and("item_13080006").as("item_13080006")
.and("item_13080007").as("item_13080007")
.and("item_13080008").as("item_13080008")
.and("item_13080009").as("item_13080009")
.and("lastLogoutTime").as("lastLogoutTime");
List<AggregationOperation> baseOperations = new ArrayList<>(List.of(
Aggregation.match(criteria),
projection,
Aggregation.sort(orderBy.equals("DESC") ? Sort.Direction.DESC : Sort.Direction.ASC, AdminConstants.MONGO_DB_KEY_LOGDAY)
));
int totalCount = 0;
if(page != null && page != 0) {
List<AggregationOperation> countOperations = new ArrayList<>(baseOperations);
countOperations.add(Aggregation.count().as("total"));
Aggregation countAggregation = Aggregation.newAggregation(countOperations);
Document countResult = mongoTemplate.aggregate(
countAggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build()),
AdminConstants.MONGO_DB_COLLECTION_ASSETS,
Document.class
).getUniqueMappedResult();
totalCount = countResult != null ? countResult.getInteger("total") : 0;
}
List<AggregationOperation> dataOperations = new ArrayList<>(baseOperations);
if(page != null && page != 0) {
int skip = (page - 1) * size;
dataOperations.add(Aggregation.skip(skip));
dataOperations.add(Aggregation.limit(size));
}
Aggregation aggregation = Aggregation.newAggregation(dataOperations);
List<T> items = mongoTemplate.aggregate(
aggregation.withOptions(AggregationOptions.builder().allowDiskUse(true).build()),
AdminConstants.MONGO_DB_COLLECTION_ASSETS,
clazz
).getMappedResults();
return new MongoPageResult<>(items, totalCount);
}
}

View File

@@ -54,6 +54,15 @@ public class IndicatorsUserCreateService extends IndicatorsLogLoadServiceBase {
if (indicatorsLog instanceof UserCreateLogInfo logInfo) {
try {
boolean exists = indicatorUserCreateRepository.existsByLogDayAndUserGuid(
logInfo.getLogDay(),
logInfo.getUserGuid()
);
if (exists) {
log.debug("Duplicate data skipped - logDay: {}, userGuid: {}",
logInfo.getLogDay(), logInfo.getUserGuid());
return;
}
indicatorUserCreateRepository.save(logInfo);
} catch (Exception e) {
log.error("Error Repository Write UserCreateLogInfo: {}, Message: {}", logInfo, e.getMessage());

View File

@@ -71,6 +71,15 @@ public class IndicatorsUserLoginService extends IndicatorsLogLoadServiceBase {
if (indicatorsLog instanceof UserLoginLogInfo logInfo) {
try {
boolean exists = indicatorUserLoginRepository.existsByLogDayAndUserGuid(
logInfo.getLogDay(),
logInfo.getUserGuid()
);
if (exists) {
log.debug("Duplicate data skipped - logDay: {}, userGuid: {}",
logInfo.getLogDay(), logInfo.getUserGuid());
return;
}
indicatorUserLoginRepository.save(logInfo);
} catch (Exception e) {
log.error("Error Repository Write UserLoginLogInfo: {}, Message: {}", logInfo, e.getMessage());

View File

@@ -1,6 +1,8 @@
package com.caliverse.admin.mongodb.service;
import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.entity.log.LogCategory;
import com.caliverse.admin.domain.request.HistoryRequest;
import com.caliverse.admin.global.common.constants.AdminConstants;
import com.caliverse.admin.mongodb.entity.DBType;
@@ -31,22 +33,42 @@ public class HistoryLogService {
public <T> List<T> loadHistoryData(HistoryRequest historyRequest, Class<T> class1) {
String startTime = historyRequest.getStartDt() != null ? historyRequest.getStartDt().toString() : "";
String endTime = historyRequest.getEndDt() != null ? historyRequest.getEndDt().toString() : "";
HISTORYTYPEDETAIL historyType = historyRequest.getHistoryType() != null ? historyRequest.getHistoryType() : null;
LogCategory category = historyRequest.getCategory() != null ? historyRequest.getCategory() : null;
LogAction action = historyRequest.getAction() != null ? historyRequest.getAction() : null;
String user = historyRequest.getUserMail() != null ? historyRequest.getUserMail() : "";
DBType dbType = historyRequest.getDbType() != null ? historyRequest.getDbType() : null;
String status = historyRequest.getStatus() != null ? historyRequest.getStatus() : "";
List<AggregationOperation> operations = new ArrayList<>();
Criteria criteria = null;
operations.add(context ->
new Document("$addFields",
new Document("logTimeString",
new Document("$dateToString",
new Document("format", "%Y-%m-%d")
.append("date", "$logTime")
)
)
)
);
if(!startTime.isEmpty() && !endTime.isEmpty()) {
criteria = makeCriteria(startTime, endTime);
operations.add(Aggregation.match(criteria));
}
if(historyType != null) {
if(action != null) {
operations.add(context ->
new Document("$match",
new Document(AdminConstants.MONGO_DB_KEY_HISTORY_TYPE, historyType)
new Document(AdminConstants.MONGO_DB_KEY_CATEGORY, category)
)
);
}
if(action != null) {
operations.add(context ->
new Document("$match",
new Document(AdminConstants.MONGO_DB_KEY_ACTION, action)
)
);
}
@@ -54,15 +76,15 @@ public class HistoryLogService {
if(!user.isEmpty()) {
operations.add(context ->
new Document("$match",
new Document(AdminConstants.MONGO_DB_KEY_USER_ID, user)
new Document(AdminConstants.MONGO_DB_KEY_WORKER, user)
)
);
}
if(dbType != null){
if(!user.isEmpty()) {
operations.add(context ->
new Document("$match",
new Document(AdminConstants.MONGO_DB_KEY_DB_TYPE, dbType)
new Document(AdminConstants.MONGO_DB_KEY_STATUS, status)
)
);
}
@@ -71,8 +93,9 @@ public class HistoryLogService {
operations.add(context ->
new Document("$match",
new Document()
.append(AdminConstants.MONGO_DB_KEY_TABLE_NAME, historyRequest.getTableName())
.append("data._id", historyRequest.getSqlId())
.append("category", LogCategory.MARIADB)
.append("domain.tableName", historyRequest.getTableName())
.append("domain.data._id", historyRequest.getSqlId())
)
);
}
@@ -80,21 +103,21 @@ public class HistoryLogService {
// 최종 출력 형식
operations.add(context ->
new Document("$sort",
new Document(AdminConstants.MONGO_DB_KEY_TIMESTAMP, -1)
new Document(AdminConstants.MONGO_DB_KEY_LOGTIME, -1)
)
);
Aggregation aggregation = Aggregation.newAggregation(operations);
log.info("loadHistoryData Query: {}", aggregation);
AggregationResults<T> results = mongoTemplate.aggregate(aggregation, AdminConstants.MONGO_DB_COLLECTION_HISTORY_LOG, class1);
AggregationResults<T> results = mongoTemplate.aggregate(aggregation, AdminConstants.MONGO_DB_COLLECTION_BUSINESS_LOG, class1);
return results.getMappedResults();
}
protected Criteria makeCriteria(String startTime, String endTime) {
return new Criteria()
.andOperator(
Criteria.where(AdminConstants.MONGO_DB_KEY_TIMESTAMP).gte(startTime).lt(endTime)
Criteria.where("logTimeString").gte(startTime).lte(endTime)
);
}
}

View File

@@ -32,6 +32,7 @@ public class ScheduleRunnerBatch {
@Autowired private IndicatorsUserLoginService userLoginService;
@Autowired private IndicatorsCurrencyService currencyService;
@Autowired private IndicatorsItemService itemService;
@Autowired private IndicatorsSnapshotService snapshotService;
@Autowired private IndicatorsAuService auService;
@Autowired private IndicatorsDauService dauService;
@@ -81,6 +82,12 @@ public class ScheduleRunnerBatch {
itemService.collectItem(startEndTime.getStartTime(), startEndTime.getEndTime());
}
@Scheduled(cron = "00 32 0 * * *") // 매일 UTC 기준 00시 32분 00초에 실행(오래걸림)
public void snapshotInfoScheduler() {
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);
snapshotService.collectSnapshot(startEndTime.getStartTime(), startEndTime.getEndTime());
}
@Scheduled(cron = "0 01 0 * * *") // 매일 UTC 기준 00시 01분 00초에 실행
public void capacityScheduler() {
StartEndTime startEndTime = LogServiceHelper.getCurrentLogSearchEndTime(AdminConstants.STAT_DAY_NUM);

View File

@@ -37,11 +37,8 @@ public class BattleEventScheduler extends CommonScheduler {
List<BattleEvent> eventList = battleEventService.getScheduleBattleEventList();
LocalDateTime startTime = LocalDateTime.now();
List<Long> processedEventIds = new ArrayList<>();
AtomicInteger runningCount = new AtomicInteger(0);
AtomicInteger endCount = new AtomicInteger(0);
AtomicInteger waitCount = new AtomicInteger(0);
AtomicInteger stopCount = new AtomicInteger(0);
List<Long> eventIds = new ArrayList<>();
AtomicInteger processCount = new AtomicInteger(0);
try{
eventList.forEach(event -> {
@@ -89,56 +86,50 @@ public class BattleEventScheduler extends CommonScheduler {
map.put("status", change_status);
battleEventService.updateBattleEventStatus(map);
processedEventIds.add(event.getId());
runningCount.incrementAndGet();
eventIds.add(event.getId());
processCount.incrementAndGet();
}
}else if(status.equals(BattleEvent.BATTLE_STATUS.RUNNING) || status.equals(BattleEvent.BATTLE_STATUS.STOP)){
if(!(!now.isBefore(todayStart) && !now.isAfter(todayEnd))){
if(!baseDate.isBefore(end_dt.toLocalDate())){
change_status = BattleEvent.BATTLE_STATUS.END;
endCount.incrementAndGet();
processCount.incrementAndGet();
}else{
change_status = status.equals(BattleEvent.BATTLE_STATUS.STOP) ? BattleEvent.BATTLE_STATUS.STOP : BattleEvent.BATTLE_STATUS.WAIT;
if (change_status.equals(BattleEvent.BATTLE_STATUS.STOP)) {
stopCount.incrementAndGet();
processCount.incrementAndGet();
} else {
waitCount.incrementAndGet();
processCount.incrementAndGet();
}
}
log.info("battle event_id: {}, start_dt: {}, end_dt: {}, todayStart: {}, todayEnd: {} STATUS CHANGE {}", event.getId(), start_dt, end_dt, todayStart, todayEnd, change_status);
map.put("status", change_status);
battleEventService.updateBattleEventStatus(map);
processedEventIds.add(event.getId());
eventIds.add(event.getId());
}
}
});
if (!processedEventIds.isEmpty()) {
if (!eventIds.isEmpty() && (processCount.get() > 0) ) {
businessLogService.logScheduler(
LogStatus.SUCCESS,
String.format("배틀 이벤트 스케줄 처리 완료: 총 %d건 처리 (시작: %d, 종료: %d, 대기: %d, 중지: %d)",
processedEventIds.size(),
runningCount.get(),
endCount.get(),
waitCount.get(),
stopCount.get()),
String.format("배틀 이벤트 스케줄 처리 완료: 총 %d건 (처리: %d)",
eventIds.size(),
processCount.get()),
"BATTLE_EVENT_SCHEDULER",
startTime,
LocalDateTime.now(),
Map.of(
"totalEventCount", eventList.size(),
"processedCount", processedEventIds.size(),
"processedEventIds", processedEventIds,
"runningCount", runningCount.get(),
"endCount", endCount.get(),
"waitCount", waitCount.get(),
"stopCount", stopCount.get()
"processedCount", eventIds.size(),
"processedEventIds", eventIds,
"processedComplete", processCount.get()
)
);
log.info("Battle event scheduler completed: {} items processed out of {} total",
processedEventIds.size(), eventList.size());
eventIds.size(), eventList.size());
}
}catch(Exception e){
log.error("battleEventSchedule Exception: {}", e.getMessage());

View File

@@ -81,7 +81,7 @@ public class BlackListScheduler extends CommonScheduler {
}
});
if (!processedBlackListIds.isEmpty()) {
if (!processedBlackListIds.isEmpty() && (timeoutFailCount.get() > 0 || blockStartedCount.get() > 0 || blockExpiredCount.get() > 0)) {
businessLogService.logScheduler(
LogStatus.SUCCESS,
String.format("블랙리스트 스케줄 처리 완료: 총 %d건 처리 (타임아웃실패: %d, 제재시작: %d, 제재만료: %d)",

View File

@@ -73,7 +73,7 @@ public class EventScheduler extends CommonScheduler {
}
});
if (!processedEventIds.isEmpty()) {
if (!processedEventIds.isEmpty() && (timeoutCount.get() > 0 || systemMailInsertedCount.get() > 0 || finishedCount.get() > 0)) {
businessLogService.logScheduler(
LogStatus.SUCCESS,
String.format("이벤트 스케줄 처리 완료: 총 %d건 처리 (타임아웃: %d, 시스템메일등록: %d, 종료: %d)",

View File

@@ -132,7 +132,7 @@ public class LandAuctionScheduler extends CommonScheduler {
}
});
if (!processedAuctionIds.isEmpty()) {
if (!processedAuctionIds.isEmpty() && (scheduledCount.get() > 0 || startedCount.get() > 0 || endedSuccessCount.get() > 0 || endedFailCount.get() > 0 || canceledCount.get() > 0)) {
businessLogService.logScheduler(
LogStatus.SUCCESS,
String.format("토지 경매 스케줄 처리 완료: 총 %d건 처리 (예약시작: %d, 경매시작: %d, 성공종료: %d, 실패종료: %d, 취소: %d)",

View File

@@ -103,7 +103,7 @@ public class MailScheduler extends CommonScheduler {
}
});
if (processedCount.get() > 0) {
if (processedCount.get() > 0 && (directSendCount.get() > 0 || scheduledCount.get() > 0)) {
businessLogService.logScheduler(
LogStatus.SUCCESS,
String.format("메일 스케줄 처리 완료: 총 %d건 처리 (즉시발송: %d건, 예약등록: %d건)",

View File

@@ -67,6 +67,10 @@ public class NoticeScheduler extends CommonScheduler {
noticeList.forEach(notice -> {
String key = "notice-" + notice.getId();
if (!schedulerService.isTaskExist(key)) {
if(notice.getEndDt().isBefore(startTime)){
noticeService.updateNoticeStatus(notice.getId(), InGame.SENDSTATUS.FAIL);
return;
}
processedCount.incrementAndGet();
Runnable taskRunner = new Runnable() {
@@ -137,7 +141,6 @@ public class NoticeScheduler extends CommonScheduler {
}
// 특정시간
case TIME -> {
timeTypeCount.incrementAndGet();
LocalDateTime now_date = LocalDateTime.now();
LocalDateTime start_date = notice.getSendDt();
@@ -149,6 +152,8 @@ public class NoticeScheduler extends CommonScheduler {
InGame.SENDSTATUS status = notice.getSendStatus();
Long id = notice.getId();
timeTypeCount.incrementAndGet();
if(status.equals(InGame.SENDSTATUS.WAIT)) noticeService.updateNoticeStatus(id, InGame.SENDSTATUS.RUNNING);
if (now_time.equals(repeat_time)) {
@@ -187,7 +192,7 @@ public class NoticeScheduler extends CommonScheduler {
}
});
if (processedCount.get() > 0) {
if (oneTimeCount.get() > 0 || repeatCount.get() > 0 || timeTypeCount.get() > 0) {
businessLogService.logScheduler(
LogStatus.SUCCESS,
String.format("공지사항 스케줄 처리 완료: 총 %d건 처리 (일회성: %d건, 반복: %d건, 특정시간: %d건, 실패: %d건)",

View File

@@ -1,14 +1,17 @@
server:
tomcat:
max-http-form-post-size: 50MB
max-swallow-size: 50MB
max-http-form-post-size: 100MB
max-swallow-size: 100MB
spring:
servlet:
multipart:
max-file-size: 5MB
max-request-size: 10MB
max-file-size: 50MB
max-request-size: 100MB
file-size-threshold: 2KB
data:
mongodb:
auto-index-creation: true
jwt:
secret_key: '81b659967735aea6e4cb0467d04ea12c4a6432b415254f59825055680f59a9823fec5a15e9adbd246b1365ef1522580477691bc5cb56a9364143e7d9385d9912'
expiration: 86400000 # a day
@@ -30,6 +33,16 @@ spring:
password:
expiration-days: 180
batch:
delay:
between:
dates: 30000 #30초
services: 500 #5초
chunks: 60000 #60초
chunk:
size: 30 #30일
open-ai:
key: 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
url: https://api.openai.com/v1/