API 관리 > API 호출로그 목록 취득하여 표시

main
유지인 2025-11-11 16:43:12 +09:00
parent fade8f5a92
commit 94529f014e
6 changed files with 171 additions and 122 deletions

View File

@ -101,6 +101,29 @@ public class ApiManagementController {
return result;
}
/**
* API > API
* @param params
* @param model
* @param response
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/admins/mgmtApiLog/list.do", method = RequestMethod.POST)
public HashMap<String, Object> getMgmtApiLogList(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletResponse response, HttpServletRequest request) throws Exception {
HashMap<String, Object> result = new HashMap<String, Object>();
List<?> listData = apiManagementService.selectWebApiLogList(params);
result.put("code", "SUCCESS");
result.put("msg", "API 호출 로그 목록 조회를 성공했습니다.");
result.put("data", listData);
return result;
}
/**
* API > API
* @param params

View File

@ -11,6 +11,8 @@ public interface ApiManagementMapper {
public List<?> selectInfo(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception;
public void saveInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectDetailInfo(HashMap<String, Object> params) throws Exception;

View File

@ -11,6 +11,8 @@ public interface ApiManagementService {
public List<?> selectInfo(HashMap<String, Object> params) throws Exception;
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception;
public void saveInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectDetailInfo(HashMap<String, Object> params) throws Exception;

View File

@ -21,6 +21,11 @@ public class ApiManagementServiceImpl implements ApiManagementService {
return masterMapper.selectInfo(params);
}
@Override
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogList(params);
}
@Override
public void saveInfo(HashMap<String, Object> params) throws Exception {
masterMapper.saveInfo(params);

View File

@ -22,13 +22,39 @@
<!-- WHERE RN BETWEEN #{firstIndex} + 1 AND #{firstIndex} + #{recordCountPerPage} -->
</select>
<insert id="saveInfo" parameterType="map">
<!-- API 관리 > API 호출 로그 목록 표시 -->
<select id="selectWebApiLogList" parameterType="map" resultType="egovMap">
SELECT TB.RN
,TB.LOG_SEQ
,SUBSTR(TB.API_KEY, 1, 10) || '...' AS API_KEY_CONCAT
,TB.API_KEY
,TB.ACCESS_ID
,TB.ACCESS_TYPE
,TB.ACCESS_TABLE
,TO_CHAR(TB.ACCESS_DT, 'YYYY-MM-DD HH24:MI') AS ACCESS_DT
,TB.IP_ADDRESS
,TO_CHAR(LAST_VALUE(ROWNUM) OVER (ORDER BY ROWNUM ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)) AS TOTALROWS
FROM (SELECT LOG_SEQ
,API_KEY
,ACCESS_ID
,ACCESS_TYPE
,ACCESS_TABLE
,ACCESS_DT
,IP_ADDRESS
,ROW_NUMBER() OVER(ORDER BY LOG_SEQ DESC) RN
,COUNT(*) OVER () AS TOTALROWS
FROM WEB_API_LOG
WHERE 1=1
) TB
</select>
<!-- <insert id="saveInfo" parameterType="map">
<![CDATA[
INSERT INTO WEB_COMMUNITY
SELECT NVL(MAX(IDX),0) + 1, #{name}, #{password}, #{email}, #{homepage}, #{subject}, #{content}, NVL(MAX(IDX),0) + 1, 0, #{fileName1}, #{saveName1}, SYSDATE, 0, #{topnotice}, #{fileName2}, #{saveName2}, #{fileName3}, #{saveName3}
FROM WEB_COMMUNITY
]]>
</insert>
</insert> -->
<!-- <select id="selectDetailInfo" parameterType="map" resultType="egovMap">
SELECT IDX, SUBJECT, EMAIL, HOMEPAGE, SAVENAME, FILENAME, SAVENAME2, FILENAME2, SAVENAME3, FILENAME3, CONTENT, NAME, READCOUNT, TO_CHAR(DATETIME,'YYYY-MM-DD') DATETIME, SEQ

View File

@ -266,81 +266,27 @@
<div class="table-container">
<h3>API 호출 로그</h3>
<table>
<colgroup>
<col style="width: 3%">
<col style="width: 7%">
<col style="width: 5%">
<col style="width: 15%">
<col style="width: auto">
<col style="width: 15%">
<col style="width: 5%">
</colgroup>
<thead>
<tr>
<th>API</th>
<th>요청방식</th>
<th>요청파라미터</th>
<th>응답상태</th>
<th>처리시간(ms)</th>
<th>응답결과</th>
<th>No.</th>
<th>API_KEY</th>
<th>ACCESS_ID</th>
<th>ACCESS_TYPE</th>
<th>ACCESS_TABLE</th>
<th>ACCESS_DT</th>
<th>IP_ADDRESS</th>
</tr>
</thead>
<tbody id="apiLogBody">
<tr>
<td>/API_CHA_085/request</td>
<td>POST</td>
<td>subCode=deowtj&prvcCode=j43o45k</td>
<td>200 OK</td>
<td>124</td>
<td><span class="status-icon success">✔</span> 성공</td>
</tr>
<tr>
<td>/API_BH_020/dc332</td>
<td>GET</td>
<td>user=beta43</td>
<td>500 INTERNAL ERROR</td>
<td>980</td>
<td><span class="status-icon error">⚠️</span> 오류</td>
</tr>
<tr>
<td>/API_BH_020/dc332</td>
<td>GET</td>
<td>user=beta43</td>
<td>500 INTERNAL ERROR</td>
<td>980</td>
<td><span class="status-icon delay">🕓</span> 지연</td>
</tr>
<tr>
<td>/API_BH_020/dc332</td>
<td>GET</td>
<td>user=beta43</td>
<td>403 Unauthorized</td>
<td>980</td>
<td><span class="status-icon error">❌</span> 실패</td>
</tr>
<tr>
<td>/API_CHA_085/request</td>
<td>POST</td>
<td>subCode=deowtj&prvcCode=j43o45k</td>
<td>200 OK</td>
<td>124</td>
<td><span class="status-icon success">✔</span> 성공</td>
</tr>
<tr>
<td>/API_BH_020/dc332</td>
<td>GET</td>
<td>user=beta43</td>
<td>500 INTERNAL ERROR</td>
<td>980</td>
<td><span class="status-icon error">⚠️</span> 오류</td>
</tr>
<tr>
<td>/API_BH_020/dc332</td>
<td>GET</td>
<td>user=beta43</td>
<td>500 INTERNAL ERROR</td>
<td>980</td>
<td><span class="status-icon delay">🕓</span> 지연</td>
</tr>
<tr>
<td>/API_BH_020/dc332</td>
<td>GET</td>
<td>user=beta43</td>
<td>403 Unauthorized</td>
<td>980</td>
<td><span class="status-icon error">❌</span> 실패</td>
</tr>
</tbody>
</table>
@ -371,6 +317,9 @@
// API 호출 통제 목록 조회
getMgmtApiList();
// API 호출로그 목록 조회
getMgmtApiLogList();
});
// API 호출 통제 목록 조회
@ -460,7 +409,49 @@
`;
return html;
}
// API 호출 로그 목록 조회
function getMgmtApiLogList(){
$.ajax({
type : "POST",
url : "/admins/mgmtApiLog/list.do" ,
data : {},
dataType :"json",
success : function(res){ // res.code, res.msg, res.data
if (res.code == "SUCCESS") {
let procList = res.data; //Array List
const $listContainer = $("#apiLogBody");
$listContainer.empty(); // 기존 내용 제거
// 데이터 반복
$.each(res.data, function(i, item) {
// DOM에 추가
$listContainer.append(drawApiLogList(item));
});
} else {
alert("API 호출 로그 목록 조회중 오류가 발생하였습니다. 다시 시도해주세요.");
}
},
error : function(response){
alert("API 호출 로그 목록 조회중 내부 오류가 발생하였습니다. 다시 시도해주세요.");
}
});
}
function drawApiLogList(item) {
// HTML 문자열 생성
const html = `
<tr data-idx="\${item.logSeq}">
<td>\${item.rn}</td>
<td title="\${item.apiKey}">\${item.apiKeyConcat}</td>
<td>\${item.accessId}</td>
<td>\${item.accessType}</td>
<td>\${item.accessTable}</td>
<td>\${item.accessDt}</td>
<td>\${item.ipAddress}</td>
</tr>
`;
return html;
}
// Chart.js: 일일 접속량
const ctx = document.getElementById('trafficChart');
new Chart(ctx, {
@ -484,64 +475,64 @@
// 예시 데이터 (100개 생성)
const apiLogs = Array.from({ length: 100 }, (_, i) => ({
api: i % 2 === 0 ? "/API_CHA_085/request" : "/API_BH_020/dc332",
method: ["GET", "POST", "PUT"][Math.floor(Math.random() * 3)],
params: `subCode=test${i}&prvcCode=x${i}`,
status: [ "200 OK", "404 NOT FOUND", "500 INTERNAL ERROR" ][Math.floor(Math.random() * 3)],
time: Math.floor(Math.random() * 500),
result: ["성공", "지연", "실패"][Math.floor(Math.random() * 3)]
}));
// const apiLogs = Array.from({ length: 100 }, (_, i) => ({
// api: i % 2 === 0 ? "/API_CHA_085/request" : "/API_BH_020/dc332",
// method: ["GET", "POST", "PUT"][Math.floor(Math.random() * 3)],
// params: `subCode=test${i}&prvcCode=x${i}`,
// status: [ "200 OK", "404 NOT FOUND", "500 INTERNAL ERROR" ][Math.floor(Math.random() * 3)],
// time: Math.floor(Math.random() * 500),
// result: ["성공", "지연", "실패"][Math.floor(Math.random() * 3)]
// }));
const rowsPerPage = 10;
let currentPage = 1;
// const rowsPerPage = 10;
// let currentPage = 1;
function renderTable(page) {
const tableBody = document.getElementById("apiLogBody");
tableBody.innerHTML = "";
// function renderTable(page) {
// const tableBody = document.getElementById("apiLogBody");
// tableBody.innerHTML = "";
const start = (page - 1) * rowsPerPage;
const end = start + rowsPerPage;
const pageData = apiLogs.slice(start, end);
// const start = (page - 1) * rowsPerPage;
// const end = start + rowsPerPage;
// const pageData = apiLogs.slice(start, end);
pageData.forEach(row => {
const tr = document.createElement("tr");
tr.innerHTML += '<td>' + row.api + '</td><td>' + row.method + '</td><td>' + row.params + '</td><td>' + row.status + '</td><td>' + row.time + '</td><td>' + getResultIcon(row.result) + ' ' +row.result + '</td>';
tableBody.appendChild(tr);
});
}
// pageData.forEach(row => {
// const tr = document.createElement("tr");
// tr.innerHTML += '<td>' + row.api + '</td><td>' + row.method + '</td><td>' + row.params + '</td><td>' + row.status + '</td><td>' + row.time + '</td><td>' + getResultIcon(row.result) + ' ' +row.result + '</td>';
// tableBody.appendChild(tr);
// });
// }
function renderPagination() {
const totalPages = Math.ceil(apiLogs.length / rowsPerPage);
const pagination = document.getElementById("pagination");
pagination.innerHTML = "";
// function renderPagination() {
// const totalPages = Math.ceil(apiLogs.length / rowsPerPage);
// const pagination = document.getElementById("pagination");
// pagination.innerHTML = "";
for (let i = 1; i <= totalPages; i++) {
const btn = document.createElement("button");
btn.textContent = i;
if (i === currentPage) btn.classList.add("active");
btn.addEventListener("click", () => {
currentPage = i;
renderTable(currentPage);
renderPagination();
});
pagination.appendChild(btn);
}
}
// for (let i = 1; i <= totalPages; i++) {
// const btn = document.createElement("button");
// btn.textContent = i;
// if (i === currentPage) btn.classList.add("active");
// btn.addEventListener("click", () => {
// currentPage = i;
// renderTable(currentPage);
// renderPagination();
// });
// pagination.appendChild(btn);
// }
// }
function getResultIcon(result) {
if (result === "성공")
return `<span style="color:#22c55e;">✔</span>`;
if (result === "실패")
return `<span style="color:#ef4444;">⚠</span>`;
if (result === "지연")
return `<span style="color:#3b82f6;">⏱</span>`;
return "";
}
// function getResultIcon(result) {
// if (result === "성공")
// return `<span style="color:#22c55e;">✔</span>`;
// if (result === "실패")
// return `<span style="color:#ef4444;">⚠</span>`;
// if (result === "지연")
// return `<span style="color:#3b82f6;">⏱</span>`;
// return "";
// }
// 초기 렌더링
renderTable(currentPage);
renderPagination();
// renderTable(currentPage);
// renderPagination();
</script>
</body>