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; 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 * API > API
* @param params * @param params

View File

@ -11,6 +11,8 @@ public interface ApiManagementMapper {
public List<?> selectInfo(HashMap<String, Object> params) throws Exception; 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 void saveInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectDetailInfo(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<?> 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 void saveInfo(HashMap<String, Object> params) throws Exception;
// public EgovMap selectDetailInfo(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); return masterMapper.selectInfo(params);
} }
@Override
public List<?> selectWebApiLogList(HashMap<String, Object> params) throws Exception {
return masterMapper.selectWebApiLogList(params);
}
@Override @Override
public void saveInfo(HashMap<String, Object> params) throws Exception { public void saveInfo(HashMap<String, Object> params) throws Exception {
masterMapper.saveInfo(params); masterMapper.saveInfo(params);

View File

@ -22,13 +22,39 @@
<!-- WHERE RN BETWEEN #{firstIndex} + 1 AND #{firstIndex} + #{recordCountPerPage} --> <!-- WHERE RN BETWEEN #{firstIndex} + 1 AND #{firstIndex} + #{recordCountPerPage} -->
</select> </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[ <![CDATA[
INSERT INTO WEB_COMMUNITY 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} 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 FROM WEB_COMMUNITY
]]> ]]>
</insert> </insert> -->
<!-- <select id="selectDetailInfo" parameterType="map" resultType="egovMap"> <!-- <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 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"> <div class="table-container">
<h3>API 호출 로그</h3> <h3>API 호출 로그</h3>
<table> <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> <thead>
<tr> <tr>
<th>API</th> <th>No.</th>
<th>요청방식</th> <th>API_KEY</th>
<th>요청파라미터</th> <th>ACCESS_ID</th>
<th>응답상태</th> <th>ACCESS_TYPE</th>
<th>처리시간(ms)</th> <th>ACCESS_TABLE</th>
<th>응답결과</th> <th>ACCESS_DT</th>
<th>IP_ADDRESS</th>
</tr> </tr>
</thead> </thead>
<tbody id="apiLogBody"> <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> </tbody>
</table> </table>
@ -371,6 +317,9 @@
// API 호출 통제 목록 조회 // API 호출 통제 목록 조회
getMgmtApiList(); getMgmtApiList();
// API 호출로그 목록 조회
getMgmtApiLogList();
}); });
// API 호출 통제 목록 조회 // API 호출 통제 목록 조회
@ -461,6 +410,48 @@
return html; 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: 일일 접속량 // Chart.js: 일일 접속량
const ctx = document.getElementById('trafficChart'); const ctx = document.getElementById('trafficChart');
new Chart(ctx, { new Chart(ctx, {
@ -484,64 +475,64 @@
// 예시 데이터 (100개 생성) // 예시 데이터 (100개 생성)
const apiLogs = Array.from({ length: 100 }, (_, i) => ({ // const apiLogs = Array.from({ length: 100 }, (_, i) => ({
api: i % 2 === 0 ? "/API_CHA_085/request" : "/API_BH_020/dc332", // api: i % 2 === 0 ? "/API_CHA_085/request" : "/API_BH_020/dc332",
method: ["GET", "POST", "PUT"][Math.floor(Math.random() * 3)], // method: ["GET", "POST", "PUT"][Math.floor(Math.random() * 3)],
params: `subCode=test${i}&prvcCode=x${i}`, // params: `subCode=test${i}&prvcCode=x${i}`,
status: [ "200 OK", "404 NOT FOUND", "500 INTERNAL ERROR" ][Math.floor(Math.random() * 3)], // status: [ "200 OK", "404 NOT FOUND", "500 INTERNAL ERROR" ][Math.floor(Math.random() * 3)],
time: Math.floor(Math.random() * 500), // time: Math.floor(Math.random() * 500),
result: ["성공", "지연", "실패"][Math.floor(Math.random() * 3)] // result: ["성공", "지연", "실패"][Math.floor(Math.random() * 3)]
})); // }));
const rowsPerPage = 10; // const rowsPerPage = 10;
let currentPage = 1; // let currentPage = 1;
function renderTable(page) { // function renderTable(page) {
const tableBody = document.getElementById("apiLogBody"); // const tableBody = document.getElementById("apiLogBody");
tableBody.innerHTML = ""; // tableBody.innerHTML = "";
const start = (page - 1) * rowsPerPage; // const start = (page - 1) * rowsPerPage;
const end = start + rowsPerPage; // const end = start + rowsPerPage;
const pageData = apiLogs.slice(start, end); // const pageData = apiLogs.slice(start, end);
pageData.forEach(row => { // pageData.forEach(row => {
const tr = document.createElement("tr"); // 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>'; // 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); // tableBody.appendChild(tr);
}); // });
} // }
function renderPagination() { // function renderPagination() {
const totalPages = Math.ceil(apiLogs.length / rowsPerPage); // const totalPages = Math.ceil(apiLogs.length / rowsPerPage);
const pagination = document.getElementById("pagination"); // const pagination = document.getElementById("pagination");
pagination.innerHTML = ""; // pagination.innerHTML = "";
for (let i = 1; i <= totalPages; i++) { // for (let i = 1; i <= totalPages; i++) {
const btn = document.createElement("button"); // const btn = document.createElement("button");
btn.textContent = i; // btn.textContent = i;
if (i === currentPage) btn.classList.add("active"); // if (i === currentPage) btn.classList.add("active");
btn.addEventListener("click", () => { // btn.addEventListener("click", () => {
currentPage = i; // currentPage = i;
renderTable(currentPage); // renderTable(currentPage);
renderPagination(); // renderPagination();
}); // });
pagination.appendChild(btn); // pagination.appendChild(btn);
} // }
} // }
function getResultIcon(result) { // function getResultIcon(result) {
if (result === "성공") // if (result === "성공")
return `<span style="color:#22c55e;">✔</span>`; // return `<span style="color:#22c55e;">✔</span>`;
if (result === "실패") // if (result === "실패")
return `<span style="color:#ef4444;">⚠</span>`; // return `<span style="color:#ef4444;">⚠</span>`;
if (result === "지연") // if (result === "지연")
return `<span style="color:#3b82f6;">⏱</span>`; // return `<span style="color:#3b82f6;">⏱</span>`;
return ""; // return "";
} // }
// 초기 렌더링 // 초기 렌더링
renderTable(currentPage); // renderTable(currentPage);
renderPagination(); // renderPagination();
</script> </script>
</body> </body>