GwMetric 테이블 변경
This commit is contained in:
@@ -2,5 +2,6 @@
|
||||
GET {{emsUrl}}/kjb/gw-metrics/after-timeslice/2025-12-02_01:00:00.json
|
||||
|
||||
|
||||
|
||||
### Pretty Print
|
||||
GET {{emsUrl}}/kjb/gw-metrics/after-timeslice/2025-12-02_01:00:00.json?pretty=true
|
||||
@@ -33,6 +33,10 @@
|
||||
|
||||
# Spring Bean 설정 및 리소스 실시간 반영 (경로 주의)
|
||||
-javaagent:C:\path\to\hotswap-agent.jar
|
||||
|
||||
|
||||
-XX:HotswapAgent=fatjar
|
||||
-Dhotswap.agent.disablePlugin=org.hotswap.agent.plugin.ibatis.IBatisPlugin,org.hotswap.agent.plugin.mybatis.MyBatisPlugin
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
@@ -61,18 +61,39 @@ public class ObpGwMetricDAO extends SqlMapClientTemplateDao {
|
||||
}
|
||||
|
||||
/**
|
||||
* URI 조회 (HTTP_ADAPTER_EXTRA_LOG)
|
||||
* URI 및 HTTP Method 조회 결과
|
||||
*/
|
||||
public static class UriMethodResult {
|
||||
private final Map<String, String> uriMap;
|
||||
private final Map<String, String> methodMap;
|
||||
|
||||
public UriMethodResult(Map<String, String> uriMap, Map<String, String> methodMap) {
|
||||
this.uriMap = uriMap;
|
||||
this.methodMap = methodMap;
|
||||
}
|
||||
|
||||
public Map<String, String> getUriMap() {
|
||||
return uriMap;
|
||||
}
|
||||
|
||||
public Map<String, String> getMethodMap() {
|
||||
return methodMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* URI 및 HTTP Method 조회 (HTTP_ADAPTER_EXTRA_LOG)
|
||||
* - GUID = TSEAILG1X.EAISVCSERNO와 매핑
|
||||
* - SERVICE_PROCESS_NUMBER = 100 (인바운드 요청)
|
||||
*
|
||||
* @param schemaId DB 스키마 ID
|
||||
* @param eaiSvcSernos EAI 서비스 일련번호 목록 (GUID)
|
||||
* @return eaiSvcSerno → URI 맵 (예: "POST /api/v1/transfer")
|
||||
* @return UriMethodResult (eaiSvcSerno → URI 맵, eaiSvcSerno → METHOD 맵)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> selectUris(String schemaId, Set<String> eaiSvcSernos) {
|
||||
public UriMethodResult selectUrisAndMethods(String schemaId, Set<String> eaiSvcSernos) {
|
||||
if (eaiSvcSernos == null || eaiSvcSernos.isEmpty()) {
|
||||
return new HashMap<>();
|
||||
return new UriMethodResult(new HashMap<>(), new HashMap<>());
|
||||
}
|
||||
|
||||
HashMap<String, Object> paramMap = new HashMap<>();
|
||||
@@ -81,15 +102,22 @@ public class ObpGwMetricDAO extends SqlMapClientTemplateDao {
|
||||
|
||||
List<Map<String, String>> resultList = this.template.queryForList("ObpGwMetric.selectUris", paramMap);
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
Map<String, String> uriMap = new HashMap<>();
|
||||
Map<String, String> methodMap = new HashMap<>();
|
||||
for (Map<String, String> m : resultList) {
|
||||
String eaiSvcSerno = m.get("EAI_SVC_SERNO");
|
||||
String uri = m.get("URI");
|
||||
if (eaiSvcSerno != null && uri != null) {
|
||||
result.put(eaiSvcSerno, uri);
|
||||
String method = m.get("METHOD");
|
||||
if (eaiSvcSerno != null) {
|
||||
if (uri != null) {
|
||||
uriMap.put(eaiSvcSerno, uri);
|
||||
}
|
||||
if (method != null) {
|
||||
methodMap.put(eaiSvcSerno, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return new UriMethodResult(uriMap, methodMap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.eactive.eai.rms.onl.apim.common;
|
||||
|
||||
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* REST API Controller 기본 클래스
|
||||
*
|
||||
* <p>기능:</p>
|
||||
* <ul>
|
||||
* <li>세션 체크 우회 (InterceptorSkipController)</li>
|
||||
* <li>JSON 변환 유틸리티 (pretty print 지원)</li>
|
||||
* <li>응답 크기 포맷팅</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>사용 예:</p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* @Controller
|
||||
* public class MyApiController extends BaseRestController {
|
||||
* @RequestMapping(value = "/api/something.json", produces = JSON_CONTENT_TYPE)
|
||||
* @ResponseBody
|
||||
* public String getSomething(@RequestParam(value = "pretty", required = false) Boolean pretty) {
|
||||
* List<MyDTO> data = service.getData();
|
||||
* return toJson(data, pretty);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public abstract class BaseRestController implements InterceptorSkipController {
|
||||
|
||||
/**
|
||||
* JSON 응답 Content-Type
|
||||
*/
|
||||
protected static final String JSON_CONTENT_TYPE = "application/json;charset=utf-8";
|
||||
|
||||
/**
|
||||
* 객체를 JSON 문자열로 변환
|
||||
*
|
||||
* @param object 변환할 객체
|
||||
* @param pretty true면 들여쓰기 적용 (null이면 false로 처리)
|
||||
* @return JSON 문자열
|
||||
*/
|
||||
protected String toJson(Object object, Boolean pretty) {
|
||||
GsonBuilder builder = new GsonBuilder().serializeNulls();
|
||||
if (Boolean.TRUE.equals(pretty)) {
|
||||
builder.setPrettyPrinting();
|
||||
}
|
||||
return builder.create().toJson(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 객체를 JSON 문자열로 변환 (기본: 한 줄 출력)
|
||||
*
|
||||
* @param object 변환할 객체
|
||||
* @return JSON 문자열
|
||||
*/
|
||||
protected String toJson(Object object) {
|
||||
return toJson(object, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 바이트 크기를 읽기 쉬운 형식으로 변환
|
||||
* 예: 1024 -> "1.0 KB", 1048576 -> "1.0 MB"
|
||||
*
|
||||
* @param bytes 바이트 수
|
||||
* @return 포맷된 문자열
|
||||
*/
|
||||
protected String formatByteSize(long bytes) {
|
||||
if (bytes < 1024) {
|
||||
return bytes + " B";
|
||||
} else if (bytes < 1024 * 1024) {
|
||||
return String.format("%.1f KB", bytes / 1024.0);
|
||||
} else {
|
||||
return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON 문자열의 바이트 크기 계산 (UTF-8 기준)
|
||||
*
|
||||
* @param json JSON 문자열
|
||||
* @return 바이트 수
|
||||
*/
|
||||
protected int getJsonByteSize(String json) {
|
||||
return json.getBytes(StandardCharsets.UTF_8).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON 문자열의 포맷된 바이트 크기 반환
|
||||
*
|
||||
* @param json JSON 문자열
|
||||
* @return 포맷된 크기 문자열
|
||||
*/
|
||||
protected String getFormattedJsonSize(String json) {
|
||||
return formatByteSize(getJsonByteSize(json));
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import java.time.format.DateTimeFormatter;
|
||||
* "apiId": "1ba56b82-a9c9-41e2-b3ab-ff9377667d56",
|
||||
* "apiName": "[해외송금] 가상계좌 입금실패 정보조회",
|
||||
* "apiRoutingUri": "/api/obs/remittance/remittancefail*",
|
||||
* "httpMethod": "POST",
|
||||
* "orgId": "ORG001",
|
||||
* "partnerCode": "000008-01",
|
||||
* "appId": "APP001",
|
||||
@@ -42,6 +43,9 @@ public class ObpGwMetricAfterDTO {
|
||||
@SerializedName("apiRoutingUri")
|
||||
private String apiRoutingUri;
|
||||
|
||||
@SerializedName("httpMethod")
|
||||
private String httpMethod;
|
||||
|
||||
@SerializedName("orgId")
|
||||
private String orgId;
|
||||
|
||||
@@ -74,6 +78,7 @@ public class ObpGwMetricAfterDTO {
|
||||
dto.setApiId(entity.getApiId());
|
||||
dto.setApiName(entity.getApiName());
|
||||
dto.setApiRoutingUri(entity.getUri());
|
||||
dto.setHttpMethod(entity.getMethod());
|
||||
dto.setOrgId(entity.getOrgId());
|
||||
dto.setPartnerCode(entity.getPartnerCode());
|
||||
dto.setAppId(entity.getAppId());
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.eactive.eai.rms.onl.apim.obp;
|
||||
|
||||
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.eactive.eai.rms.onl.apim.common.BaseRestController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -11,7 +9,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
@@ -20,10 +17,10 @@ import java.util.List;
|
||||
* ObpGwMetric REST Controller
|
||||
* API Gateway 시간별 거래량 지표 조회 API
|
||||
*
|
||||
* <p>세션 체크를 우회하기 위해 InterceptorSkipController 인터페이스 구현</p>
|
||||
* @see BaseRestController 세션 체크 우회 및 JSON 유틸리티 제공
|
||||
*/
|
||||
@Controller
|
||||
public class ObpGwMetricController implements InterceptorSkipController {
|
||||
public class ObpGwMetricController extends BaseRestController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ObpGwMetricController.class);
|
||||
|
||||
@@ -45,7 +42,7 @@ public class ObpGwMetricController implements InterceptorSkipController {
|
||||
*/
|
||||
@RequestMapping(
|
||||
value = "/kjb/gw-metrics/{datetime}.json",
|
||||
produces = "application/json;charset=utf-8"
|
||||
produces = JSON_CONTENT_TYPE
|
||||
)
|
||||
@ResponseBody
|
||||
public String getGwMetrics(
|
||||
@@ -65,13 +62,9 @@ public class ObpGwMetricController implements InterceptorSkipController {
|
||||
// JSON 변환 (GSON)
|
||||
String json = toJson(metrics, pretty);
|
||||
|
||||
// 응답 크기 계산 (UTF-8 기준)
|
||||
int jsonBytes = json.getBytes(StandardCharsets.UTF_8).length;
|
||||
String jsonSize = formatByteSize(jsonBytes);
|
||||
|
||||
long elapsed = System.currentTimeMillis() - startTime;
|
||||
log.info("GwMetric 조회 완료: datetime={}, count={}, size={}, elapsed={}ms",
|
||||
datetime, metrics.size(), jsonSize, elapsed);
|
||||
datetime, metrics.size(), getFormattedJsonSize(json), elapsed);
|
||||
|
||||
return json;
|
||||
|
||||
@@ -90,7 +83,7 @@ public class ObpGwMetricController implements InterceptorSkipController {
|
||||
*/
|
||||
@RequestMapping(
|
||||
value = "/kjb/gw-metrics/after-timeslice/{datetime}.json",
|
||||
produces = "application/json;charset=utf-8"
|
||||
produces = JSON_CONTENT_TYPE
|
||||
)
|
||||
@ResponseBody
|
||||
public String getGwMetricsAfterTimeslice(
|
||||
@@ -110,13 +103,9 @@ public class ObpGwMetricController implements InterceptorSkipController {
|
||||
// JSON 변환 (GSON)
|
||||
String json = toJson(metrics, pretty);
|
||||
|
||||
// 응답 크기 계산 (UTF-8 기준)
|
||||
int jsonBytes = json.getBytes(StandardCharsets.UTF_8).length;
|
||||
String jsonSize = formatByteSize(jsonBytes);
|
||||
|
||||
long elapsed = System.currentTimeMillis() - startTime;
|
||||
log.info("GwMetric after-timeslice 조회 완료: datetime={}, count={}, size={}, elapsed={}ms",
|
||||
datetime, metrics.size(), jsonSize, elapsed);
|
||||
datetime, metrics.size(), getFormattedJsonSize(json), elapsed);
|
||||
|
||||
return json;
|
||||
|
||||
@@ -125,33 +114,4 @@ public class ObpGwMetricController implements InterceptorSkipController {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 객체를 JSON 문자열로 변환
|
||||
*
|
||||
* @param object 변환할 객체
|
||||
* @param pretty true면 들여쓰기 적용
|
||||
* @return JSON 문자열
|
||||
*/
|
||||
private String toJson(Object object, Boolean pretty) {
|
||||
GsonBuilder builder = new GsonBuilder().serializeNulls();
|
||||
if (Boolean.TRUE.equals(pretty)) {
|
||||
builder.setPrettyPrinting();
|
||||
}
|
||||
return builder.create().toJson(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 바이트 크기를 읽기 쉬운 형식으로 변환
|
||||
* 예: 1024 -> "1.0 KB", 1048576 -> "1.0 MB"
|
||||
*/
|
||||
private String formatByteSize(long bytes) {
|
||||
if (bytes < 1024) {
|
||||
return bytes + " B";
|
||||
} else if (bytes < 1024 * 1024) {
|
||||
return String.format("%.1f KB", bytes / 1024.0);
|
||||
} else {
|
||||
return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ public class ObpGwMetricDTO {
|
||||
@SerializedName("apiRoutingUri")
|
||||
private String uri;
|
||||
|
||||
@SerializedName("httpMethod")
|
||||
private String method;
|
||||
|
||||
@SerializedName("attemptedCount")
|
||||
private Long attemptedCount;
|
||||
|
||||
@@ -74,6 +77,7 @@ public class ObpGwMetricDTO {
|
||||
dto.setTimeslice(formatTimeslice(entity.getTimeslice()));
|
||||
dto.setApiName(entity.getApiName());
|
||||
dto.setUri(entity.getUri());
|
||||
dto.setMethod(entity.getMethod());
|
||||
dto.setAttemptedCount(entity.getAttemptedCount());
|
||||
dto.setCompletedCount(entity.getCompletedCount());
|
||||
dto.setApiId(entity.getApiId());
|
||||
|
||||
@@ -165,7 +165,9 @@ public class ObpGwMetricManService extends BaseService {
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Map<String, String> apiNameMap = obpGwMetricDAO.selectApiNames(apigwDataSourceType.getSchema(), apiIds);
|
||||
Map<String, String> uriMap = obpGwMetricDAO.selectUris(apigwDataSourceType.getSchema(), eaiSvcSernos);
|
||||
ObpGwMetricDAO.UriMethodResult uriMethodResult = obpGwMetricDAO.selectUrisAndMethods(apigwDataSourceType.getSchema(), eaiSvcSernos);
|
||||
Map<String, String> uriMap = uriMethodResult.getUriMap();
|
||||
Map<String, String> methodMap = uriMethodResult.getMethodMap();
|
||||
log.info("[3단계] 부가정보 조회 완료: apiCount={}, eaiSvcSernoCount={}, elapsed={}ms",
|
||||
apiIds.size(), eaiSvcSernos.size(), System.currentTimeMillis() - step3Start);
|
||||
|
||||
@@ -202,7 +204,8 @@ public class ObpGwMetricManService extends BaseService {
|
||||
entity.setAttemptedCount(vo.getAttemptedCount());
|
||||
entity.setCompletedCount(vo.getCompletedCount());
|
||||
entity.setApiName(apiNameMap.get(vo.getApiId()));
|
||||
entity.setUri(uriMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 URI 조회
|
||||
entity.setUri(uriMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 URI 조회
|
||||
entity.setMethod(methodMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 HTTP Method 조회
|
||||
entity.setAppId(appIdMap.get(vo.getOrgId()));
|
||||
entity.setUpdateCount(entity.getUpdateCount() + 1); // 보정 횟수 증가
|
||||
entity.setUpdatedAt(LocalDateTime.now());
|
||||
@@ -211,7 +214,7 @@ public class ObpGwMetricManService extends BaseService {
|
||||
updateCount++;
|
||||
} else {
|
||||
// INSERT: 신규 데이터 생성
|
||||
ObpGwMetric entity = convertToEntity(vo, apiNameMap, uriMap, appIdMap);
|
||||
ObpGwMetric entity = convertToEntity(vo, apiNameMap, uriMap, methodMap, appIdMap);
|
||||
obpGwMetricService.save(entity);
|
||||
insertCount++;
|
||||
}
|
||||
@@ -249,7 +252,8 @@ public class ObpGwMetricManService extends BaseService {
|
||||
* VO → Entity 변환
|
||||
*/
|
||||
private ObpGwMetric convertToEntity(ObpGwMetricVO vo, Map<String, String> apiNameMap,
|
||||
Map<String, String> uriMap, Map<String, String> appIdMap) {
|
||||
Map<String, String> uriMap, Map<String, String> methodMap,
|
||||
Map<String, String> appIdMap) {
|
||||
ObpGwMetric entity = new ObpGwMetric();
|
||||
entity.setClientId(vo.getClientId());
|
||||
entity.setHostname(vo.getHostname());
|
||||
@@ -259,7 +263,8 @@ public class ObpGwMetricManService extends BaseService {
|
||||
entity.setAttemptedCount(vo.getAttemptedCount());
|
||||
entity.setCompletedCount(vo.getCompletedCount());
|
||||
entity.setApiName(apiNameMap.get(vo.getApiId()));
|
||||
entity.setUri(uriMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 URI 조회
|
||||
entity.setUri(uriMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 URI 조회
|
||||
entity.setMethod(methodMap.get(vo.getEaiSvcSerno())); // eaiSvcSerno로 HTTP Method 조회
|
||||
entity.setAppId(appIdMap.get(vo.getOrgId()));
|
||||
entity.setUpdateCount(0);
|
||||
entity.setCreatedAt(LocalDateTime.now());
|
||||
|
||||
@@ -66,15 +66,16 @@
|
||||
</statement>
|
||||
|
||||
<!--
|
||||
URI 조회 (HTTP_ADAPTER_EXTRA_LOG)
|
||||
URI 및 HTTP Method 조회 (HTTP_ADAPTER_EXTRA_LOG)
|
||||
- GUID = TSEAILG1X.EAISVCSERNO
|
||||
- SERVICE_PROCESS_NUMBER = 100 (인바운드 요청)
|
||||
- 결과: HTTP_METHOD + ' ' + URL (예: POST /mapi/kjbank/obp/kakaobank/v3/loan/query)
|
||||
- 결과: HTTP_METHOD (예: POST), URL (예: /mapi/kjbank/obp/kakaobank/v3/loan/query)
|
||||
-->
|
||||
<statement id="selectUris" parameterClass="java.util.HashMap" resultClass="java.util.HashMap">
|
||||
SELECT
|
||||
GUID AS EAI_SVC_SERNO,
|
||||
HTTP_METHOD || ' ' || URL AS URI
|
||||
URL AS URI,
|
||||
HTTP_METHOD AS METHOD
|
||||
FROM $schemaId$.HTTP_ADAPTER_EXTRA_LOG
|
||||
WHERE SERVICE_PROCESS_NUMBER = 100
|
||||
AND GUID IN
|
||||
|
||||
Reference in New Issue
Block a user