////////////////////////////////////////////////////////////////////////////////////////
//Page 전역 변수
////////////////////////////////////////////////////////////////////////////////////////
var MONITORING_BASE_URL = "/engine-search-api/engine/admin/monitoring";
var clusterHealthTable;
var nodeStatsTable;
var threadPoolTable;
var indexingStatsTable;
var summaryTable;
var isHealthyTable;
//Document Ready
////////////////////////////////////////////////////////////////////////////////////////
function execDocReady() {
let pluginGroups = [
[
"../reference/light-blue/lib/vendor/jquery.ui.widget.js",
"../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Templates_js_tmpl.js",
"../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Load-Image_js_load-image.js",
"../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Canvas-to-Blob_js_canvas-to-blob.js",
"../reference/light-blue/lib/jquery.iframe-transport.js",
"../reference/light-blue/lib/jquery.fileupload.js",
"../reference/light-blue/lib/jquery.fileupload-fp.js",
"../reference/light-blue/lib/jquery.fileupload-ui.js"
],
[
"../reference/jquery-plugins/select2-4.0.2/dist/css/select2_lightblue4.css",
"../reference/jquery-plugins/lou-multi-select-0.9.12/css/multiselect-lightblue4.css",
"../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select-bluelight.css",
"../reference/jquery-plugins/select2-4.0.2/dist/js/select2.min.js",
"../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.quicksearch.js",
"../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.multi-select.js",
"../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select.min.js"
],
[
"../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.min.css",
"../reference/light-blue/lib/bootstrap-datepicker.js",
"../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.full.min.js",
"../reference/lightblue4/docs/lib/widgster/widgster.js",
"../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js",
"../reference/lightblue4/docs/lib/jquery.sparkline/index.js",
"../reference/lightblue4/docs/js/charts.js"
],
[
"../reference/jquery-plugins/dataTables-1.10.16/media/css/jquery.dataTables_lightblue4.css",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/css/responsive.dataTables_lightblue4.css",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/css/select.dataTables_lightblue4.css",
"../reference/jquery-plugins/dataTables-1.10.16/media/js/jquery.dataTables.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/js/dataTables.responsive.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/js/dataTables.select.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/RowGroup/js/dataTables.rowsGroup.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/dataTables.buttons.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.html5.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.print.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/jszip.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/pdfmake.min.js",
"../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/vfs_fonts.js",
"../reference/jquery-plugins/kevalbhatt-timezone-picker-2.0.0/dist/timezone-picker.min.js",
"../reference/jquery-plugins/kevalbhatt-timezone-picker-2.0.0/dist/styles/timezone-picker.css"
]
];
loadPluginGroupsParallelAndSequential(pluginGroups)
.then(function () {
console.log("모든 플러그인 로드 완료");
$(".widget").widgster();
setSideMenu("sidebar_menu_system", "sidebar_menu_system_es_monitoring");
// 데이터 테이블 초기화
initClusterHealthTable();
initNodeStatsTable();
initThreadPoolTable();
initIndexingStatsTable();
initSummaryTable();
initIsHealthyTable();
// 초기 데이터 로드
loadClusterHealth();
// 탭 전환 이벤트
setupTabEvents();
})
.catch(function (error) {
console.error("플러그인 로드 중 오류 발생");
console.log(error);
});
}
// 데이터 테이블 열 클릭 이벤트
function dataTableClick(tempDataTable, selectedData) {
let tableId = tempDataTable.context[0].sInstance;
console.log("Table clicked: " + tableId);
}
// 데이터 테이블 렌더링 후 콜백 함수
function dataTableCallBack(settings, json) {
}
// 데이터 테이블 재그리기 후 콜백 함수
function dataTableDrawCallback(tableInfo) {
console.log(tableInfo);
$("#" + tableInfo.sInstance)
.DataTable()
.columns.adjust()
.responsive.recalc();
}
////////////////////////////////////////////////////////////////////////////////////////
// 탭 이벤트 설정
////////////////////////////////////////////////////////////////////////////////////////
function setupTabEvents() {
$('a[data-toggle="tab"]').on("shown.bs.tab", function (e) {
var target = $(e.target).attr("href");
switch (target) {
case "#tabHealth":
loadClusterHealth();
break;
case "#tabNodes":
loadNodeStats();
break;
case "#tabThreadPool":
loadThreadPool();
break;
case "#tabIndexing":
loadIndexingStats();
break;
case "#tabSummary":
loadSummary();
break;
case "#tabIsHealthy":
loadIsHealthy();
break;
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// 공통 유틸 함수
////////////////////////////////////////////////////////////////////////////////////////
function renderValue(data) {
return data ? "" + data + "" : "N/A";
}
function formatBytes(bytes) {
if (!bytes && bytes !== 0) return "N/A";
if (bytes === 0) return "0 B";
var k = 1024;
var sizes = ["B", "KB", "MB", "GB", "TB"];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
}
////////////////////////////////////////////////////////////////////////////////////////
// Is Healthy 테이블
////////////////////////////////////////////////////////////////////////////////////////
function initIsHealthyTable() {
let columnList = [
{
title: "정상여부",
data: "isHealthy",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "상태메시지",
data: "message",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
}
];
let columnDefList = [{ "defaultContent": "
N/A
", "targets": "_all" }];
isHealthyTable = dataTable_build(
"#isHealthyTable", "", "", columnList, [], columnDefList, {}, [], [], false, {}, [], false
);
}
function loadIsHealthy() {
$.ajax({
url: MONITORING_BASE_URL + "/is-healthy",
type: "GET",
dataType: "json",
statusCode: {
200: function (data) {
var isHealthy = data.response;
var table = $("#isHealthyTable").DataTable();
var message = isHealthy === true
? "클러스터 정상. 모든 모니터링 지표가 정상 범위 내입니다."
: "장애 발생. Summary 탭에서 상세 원인을 확인하세요.";
table.clear();
table.rows.add([{ isHealthy: isHealthy, message: message }]);
table.draw();
}
},
error: function () {
var table = $("#isHealthyTable").DataTable();
table.clear();
table.rows.add([{ isHealthy: null, message: "서버 연결에 실패했습니다." }]);
table.draw();
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// Cluster Health 테이블
////////////////////////////////////////////////////////////////////////////////////////
function initClusterHealthTable() {
let columnList = [
{
title: "클러스터명",
data: "clusterName",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
},
{
title: "상태",
data: "status",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "전체노드수",
data: "numberOfNodes",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "데이터노드수",
data: "numberOfDataNodes",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "활성Primary샤드",
data: "activePrimaryShards",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "활성샤드",
data: "activeShards",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "미할당샤드",
data: "unassignedShards",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "활성샤드비율(%)",
data: "activeShardsPercentAsNumber",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "대기작업수",
data: "numberOfPendingTasks",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "정상여부",
data: "isHealthy",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "상태메시지",
data: "healthMessage",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
}
];
let columnDefList = [{ "defaultContent": "N/A
", "targets": "_all" }];
clusterHealthTable = dataTable_build(
"#clusterHealthTable", "", "", columnList, [], columnDefList, {}, [], [], false, {}, [], false
);
}
function loadClusterHealth() {
$.ajax({
url: MONITORING_BASE_URL + "/health",
type: "GET",
dataType: "json",
statusCode: {
200: function (data) {
var table = $("#clusterHealthTable").DataTable();
table.clear();
table.rows.add([data.response]);
table.draw();
}
},
error: function () {
console.error("Cluster Health 데이터 로드 실패");
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// Node Stats 테이블
////////////////////////////////////////////////////////////////////////////////////////
function initNodeStatsTable() {
let columnList = [
{
title: "노드명",
data: "nodeName",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
},
{
title: "IP",
data: "ip",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "역할",
data: "nodeRole",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "Master",
data: "isMaster",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "Heap사용률(%)",
data: "heapUsedPercent",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "Heap사용량",
data: "heapUsedBytes",
render: function (data) { return renderValue(formatBytes(data)); },
className: "dt-body-center",
visible: true
},
{
title: "Heap최대",
data: "heapMaxBytes",
render: function (data) { return renderValue(formatBytes(data)); },
className: "dt-body-center",
visible: true
},
{
title: "CPU(%)",
data: "cpuPercent",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "1분평균부하",
data: "loadAverage1m",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "디스크사용률(%)",
data: "diskUsedPercent",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "디스크여유공간",
data: "diskFreeBytes",
render: function (data) { return renderValue(formatBytes(data)); },
className: "dt-body-center",
visible: true
},
{
title: "정상여부",
data: "isHealthy",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "상태메시지",
data: "healthMessage",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
}
];
let columnDefList = [{ "defaultContent": "N/A
", "targets": "_all" }];
nodeStatsTable = dataTable_build(
"#nodeStatsTable", "", "", columnList, [], columnDefList, {}, [], [], false, {}, [], false
);
}
function loadNodeStats() {
$.ajax({
url: MONITORING_BASE_URL + "/nodes",
type: "GET",
dataType: "json",
statusCode: {
200: function (data) {
var table = $("#nodeStatsTable").DataTable();
table.clear();
table.rows.add(data.response);
table.draw();
}
},
error: function () {
console.error("Node Stats 데이터 로드 실패");
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// Thread Pool 테이블
////////////////////////////////////////////////////////////////////////////////////////
function initThreadPoolTable() {
let columnList = [
{
title: "노드명",
data: "nodeName",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
},
{
title: "스레드풀명",
data: "threadPoolName",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "활성스레드수",
data: "active",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "대기열",
data: "queue",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "거부요청수",
data: "rejected",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "최대스레드수",
data: "largest",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "완료작업수",
data: "completed",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "거부발생여부",
data: "hasRejected",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "상태메시지",
data: "healthMessage",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
}
];
let columnDefList = [{ "defaultContent": "N/A
", "targets": "_all" }];
threadPoolTable = dataTable_build(
"#threadPoolTable", "", "", columnList, [], columnDefList, {}, [], [], false, {}, [], false
);
}
function loadThreadPool() {
$.ajax({
url: MONITORING_BASE_URL + "/thread-pool",
type: "GET",
dataType: "json",
statusCode: {
200: function (data) {
var table = $("#threadPoolTable").DataTable();
table.clear();
table.rows.add(data.response);
table.draw();
}
},
error: function () {
console.error("Thread Pool 데이터 로드 실패");
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// Indexing Stats 테이블
////////////////////////////////////////////////////////////////////////////////////////
function initIndexingStatsTable() {
let columnList = [
{
title: "총인덱싱수",
data: "indexTotal",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "총인덱싱시간(ms)",
data: "indexTimeInMillis",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "진행중인덱싱",
data: "indexCurrent",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "실패인덱싱수",
data: "indexFailed",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "총검색수",
data: "queryTotal",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "총검색시간(ms)",
data: "queryTimeInMillis",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "진행중검색",
data: "queryCurrent",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "총Fetch수",
data: "fetchTotal",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "총Fetch시간(ms)",
data: "fetchTimeInMillis",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "진행중Fetch",
data: "fetchCurrent",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "인덱싱실패여부",
data: "hasIndexFailed",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "상태메시지",
data: "healthMessage",
render: function (data) { return renderValue(data); },
className: "dt-body-left",
visible: true
}
];
let columnDefList = [{ "defaultContent": "N/A
", "targets": "_all" }];
indexingStatsTable = dataTable_build(
"#indexingStatsTable", "", "", columnList, [], columnDefList, {}, [], [], false, {}, [], false
);
}
function loadIndexingStats() {
$.ajax({
url: MONITORING_BASE_URL + "/indexing",
type: "GET",
dataType: "json",
statusCode: {
200: function (data) {
var table = $("#indexingStatsTable").DataTable();
table.clear();
table.rows.add([data.response]);
table.draw();
}
},
error: function () {
console.error("Indexing Stats 데이터 로드 실패");
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// Summary 테이블
////////////////////////////////////////////////////////////////////////////////////////
function initSummaryTable() {
let columnList = [
{
title: "수집시각",
data: "timestamp",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "클러스터상태",
data: "clusterHealth",
render: function (data) { return data ? renderValue(data.status) : "N/A"; },
className: "dt-body-center",
visible: true
},
{
title: "노드수",
data: "nodeStats",
render: function (data) { return data ? renderValue(data.length) : "N/A"; },
className: "dt-body-center",
visible: true
},
{
title: "스레드풀수",
data: "threadPoolStats",
render: function (data) { return data ? renderValue(data.length) : "N/A"; },
className: "dt-body-center",
visible: true
},
{
title: "인덱싱실패",
data: "indexingStats",
render: function (data) { return data ? renderValue(data.indexFailed) : "N/A"; },
className: "dt-body-center",
visible: true
},
{
title: "정상여부",
data: "isHealthy",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "전체상태",
data: "overallStatus",
render: function (data) { return renderValue(data); },
className: "dt-body-center",
visible: true
},
{
title: "문제목록",
data: "issues",
render: function (data) {
if (!data || data.length === 0) return "감지된 문제가 없습니다.";
return data.map(function (issue) {
return "" + issue + "";
}).join("
");
},
className: "dt-body-left",
visible: true
}
];
let columnDefList = [{ "defaultContent": "N/A
", "targets": "_all" }];
summaryTable = dataTable_build(
"#summaryTable", "", "", columnList, [], columnDefList, {}, [], [], false, {}, [], false
);
}
function loadSummary() {
$.ajax({
url: MONITORING_BASE_URL + "/summary",
type: "GET",
dataType: "json",
statusCode: {
200: function (data) {
var table = $("#summaryTable").DataTable();
table.clear();
table.rows.add([data.response]);
table.draw();
}
},
error: function () {
console.error("Summary 데이터 로드 실패");
}
});
}
////////////////////////////////////////////////////////////////////////////////////////
// 데이터 테이블 렌더링 & Ajax 호출 종료
////////////////////////////////////////////////////////////////////////////////////////