实现日志收集功能
This commit is contained in:
@@ -360,7 +360,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<!-- 进程信息展示 -->
|
||||
<div id="processInfoContainer" class="mt-8">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">进程信息</h3>
|
||||
@@ -478,8 +478,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统日志 图表 -->
|
||||
<div id="logChartContainer" class="chart-container h-80 hidden">
|
||||
<!-- 系统日志 信息 -->
|
||||
<div id="logInfoContainer" class="mt-8 hidden">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">系统日志</h3>
|
||||
<div class="overflow-x-auto">
|
||||
<table id="logTable" class="min-w-full bg-white rounded-lg overflow-hidden shadow-md">
|
||||
@@ -496,6 +496,8 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- 日志信息分页容器 -->
|
||||
<div id="logPaginationContainer" class="mt-4"></div>
|
||||
</div>
|
||||
|
||||
<!-- 缩放控件已移动到各个图表容器内 -->
|
||||
|
||||
@@ -7,6 +7,7 @@ let state = {
|
||||
customStartTime: '',
|
||||
customEndTime: '',
|
||||
currentInterval: '3m', // 固定10分钟区间
|
||||
currentDeviceID: '', // 当前选中的服务器ID
|
||||
historyMetrics: {}, // 存储历史指标数据
|
||||
autoRefreshEnabled: false, // 自动刷新开关状态,默认关闭
|
||||
lastMetricsUpdate: null, // 记录上次指标更新时间
|
||||
@@ -101,12 +102,22 @@ function updateAutoRefreshInterval() {
|
||||
// 初始化自定义时间范围
|
||||
function initCustomTimeRange() {
|
||||
const now = new Date();
|
||||
// 默认显示过去24小时
|
||||
const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
||||
// 默认显示过去1小时
|
||||
const oneHourAgo = new Date(now.getTime() - 1 * 60 * 60 * 1000);
|
||||
|
||||
// 直接使用ISO字符串,包含完整的时区信息
|
||||
state.customStartTime = twentyFourHoursAgo.toISOString();
|
||||
state.customStartTime = oneHourAgo.toISOString();
|
||||
state.customEndTime = now.toISOString();
|
||||
|
||||
// 更新日期选择器输入框的值
|
||||
const startTimeInput = document.getElementById('customStartTime');
|
||||
const endTimeInput = document.getElementById('customEndTime');
|
||||
|
||||
if (startTimeInput && endTimeInput) {
|
||||
// 将ISO字符串转换为datetime-local格式(YYYY-MM-DDTHH:MM)
|
||||
startTimeInput.value = oneHourAgo.toISOString().slice(0, 16);
|
||||
endTimeInput.value = now.toISOString().slice(0, 16);
|
||||
}
|
||||
}
|
||||
|
||||
// 页面切换
|
||||
@@ -125,9 +136,13 @@ function switchPage() {
|
||||
if (hash === '#servers') {
|
||||
showContent('serversContent');
|
||||
loadAllServers();
|
||||
// 清除当前设备ID,避免在服务器列表页显示特定服务器的数据
|
||||
state.currentDeviceID = '';
|
||||
} else if (hash === '#devices') {
|
||||
showContent('devicesContent');
|
||||
loadDeviceManagementList();
|
||||
// 清除当前设备ID
|
||||
state.currentDeviceID = '';
|
||||
} else if (hash === '#serverMonitor' || hash.startsWith('#serverMonitor/')) {
|
||||
showContent('serverMonitorContent');
|
||||
|
||||
@@ -137,6 +152,9 @@ function switchPage() {
|
||||
deviceId = hash.split('/')[1];
|
||||
}
|
||||
|
||||
// 直接设置当前设备ID,确保loadMetrics能使用正确的设备ID
|
||||
state.currentDeviceID = deviceId;
|
||||
|
||||
// 加载服务器信息
|
||||
if (deviceId) {
|
||||
loadServerInfo(deviceId);
|
||||
@@ -146,6 +164,8 @@ function switchPage() {
|
||||
} else {
|
||||
showContent('homeContent');
|
||||
loadHomeData();
|
||||
// 清除当前设备ID
|
||||
state.currentDeviceID = '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,7 +753,7 @@ function initDetailedCharts() {
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true,
|
||||
enabled: true
|
||||
},
|
||||
pinch: {
|
||||
enabled: true
|
||||
@@ -802,7 +822,7 @@ function initDetailedCharts() {
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true,
|
||||
enabled: true
|
||||
},
|
||||
pinch: {
|
||||
enabled: true
|
||||
@@ -872,7 +892,7 @@ function initDetailedCharts() {
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true,
|
||||
enabled: true
|
||||
},
|
||||
pinch: {
|
||||
enabled: true
|
||||
@@ -950,11 +970,10 @@ function initDetailedCharts() {
|
||||
label: function(context) {
|
||||
const label = context.dataset.label || '';
|
||||
const value = context.parsed.y;
|
||||
const rawValue = context.raw.y;
|
||||
// 第二行显示实际值
|
||||
return [
|
||||
`${label}: ${value} MB`,
|
||||
`实际值: ${rawValue} MB`
|
||||
`实际值: ${value} MB`
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1043,11 +1062,10 @@ function initDetailedCharts() {
|
||||
label: function(context) {
|
||||
const label = context.dataset.label || '';
|
||||
const value = context.parsed.y;
|
||||
const rawValue = context.raw.y;
|
||||
// 第二行显示实际值
|
||||
return [
|
||||
`${label}: ${value} MB/s`,
|
||||
`实际值: ${rawValue} MB/s`
|
||||
`实际值: ${value} MB/s`
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1196,7 +1214,18 @@ async function fetchMetric(metricType, aggregation = 'average') {
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data.data;
|
||||
|
||||
// 确保返回的数据是数组格式
|
||||
if (metricType === 'disk') {
|
||||
// 磁盘数据可能是对象格式,需要特殊处理
|
||||
return data.data || {};
|
||||
} else if (metricType === 'network') {
|
||||
// 网络数据可能是对象格式,需要特殊处理
|
||||
return data.data || {};
|
||||
} else {
|
||||
// 其他数据应该是数组格式
|
||||
return Array.isArray(data.data) ? data.data : [];
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化时间,统一格式避免图表误解
|
||||
@@ -1259,6 +1288,9 @@ async function loadMetrics() {
|
||||
statusIndicator.className = 'w-2 h-2 bg-red-500 rounded-full animate-pulse';
|
||||
lastRefreshTime.textContent = `上次刷新: 失败`;
|
||||
}
|
||||
|
||||
// 即使发生错误,也要尝试初始化图表,避免页面空白
|
||||
initDetailedCharts();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1450,6 +1482,9 @@ function handleWebSocketMessage(message) {
|
||||
// 加载服务器信息
|
||||
async function loadServerInfo(deviceId) {
|
||||
try {
|
||||
// 将设备ID存储到全局状态
|
||||
state.currentDeviceID = deviceId;
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/devices/${deviceId}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch server info');
|
||||
@@ -1464,6 +1499,9 @@ async function loadServerInfo(deviceId) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load server info:', error);
|
||||
// 即使请求失败,也要将设备ID存储到全局状态
|
||||
state.currentDeviceID = deviceId;
|
||||
|
||||
// 使用模拟数据
|
||||
const serverInfoDisplay = document.getElementById('serverInfoDisplay');
|
||||
if (serverInfoDisplay) {
|
||||
@@ -1475,6 +1513,12 @@ async function loadServerInfo(deviceId) {
|
||||
// 处理指标更新
|
||||
function handleMetricsUpdate(message) {
|
||||
const { device_id, metrics } = message;
|
||||
|
||||
// 只处理当前选中设备的WebSocket消息
|
||||
if (state.currentDeviceID && device_id !== state.currentDeviceID) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 格式化数据,确保updateStatusCards函数能正确处理
|
||||
const formattedMetrics = {
|
||||
cpu: metrics.cpu,
|
||||
@@ -1855,12 +1899,18 @@ function updateHistoryMetrics(metrics) {
|
||||
|
||||
// 更新图表数据
|
||||
function updateCharts(cpuData, memoryData, diskData, networkData) {
|
||||
// 确保数据格式正确
|
||||
const safeCpuData = Array.isArray(cpuData) ? cpuData : [];
|
||||
const safeMemoryData = Array.isArray(memoryData) ? memoryData : [];
|
||||
const safeDiskData = typeof diskData === 'object' && diskData !== null ? diskData : {};
|
||||
const safeNetworkData = typeof networkData === 'object' && networkData !== null ? networkData : {};
|
||||
|
||||
// 保存待处理的图表更新数据
|
||||
state.pendingChartUpdate = {
|
||||
cpuData,
|
||||
memoryData,
|
||||
diskData,
|
||||
networkData
|
||||
cpuData: safeCpuData,
|
||||
memoryData: safeMemoryData,
|
||||
diskData: safeDiskData,
|
||||
networkData: safeNetworkData
|
||||
};
|
||||
|
||||
// 使用节流机制更新图表
|
||||
@@ -2619,18 +2669,7 @@ function bindEvents() {
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化自定义时间输入框
|
||||
const now = new Date();
|
||||
const startTimeInput = document.getElementById('customStartTime');
|
||||
const endTimeInput = document.getElementById('customEndTime');
|
||||
if (startTimeInput && endTimeInput) {
|
||||
// 默认显示过去24小时
|
||||
const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
||||
|
||||
// 显示本地时间格式,YYYY-MM-DDTHH:MM
|
||||
startTimeInput.value = twentyFourHoursAgo.toISOString().slice(0, 16);
|
||||
endTimeInput.value = now.toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
|
||||
// 缩放控件事件处理
|
||||
const zoomOutBtn = document.getElementById('zoomOutBtn');
|
||||
@@ -2722,27 +2761,49 @@ async function loadNetworkInterfaces() {
|
||||
// 更新当前时间范围显示
|
||||
const updateTimeRangeDisplay = () => {
|
||||
let displayText = '';
|
||||
switch(state.currentTimeRange) {
|
||||
case '30m':
|
||||
displayText = '过去30分钟';
|
||||
break;
|
||||
case '1h':
|
||||
displayText = '过去1小时';
|
||||
break;
|
||||
case '2h':
|
||||
displayText = '过去2小时';
|
||||
break;
|
||||
case '6h':
|
||||
displayText = '过去6小时';
|
||||
break;
|
||||
case '12h':
|
||||
displayText = '过去12小时';
|
||||
break;
|
||||
case '24h':
|
||||
displayText = '过去24小时';
|
||||
break;
|
||||
default:
|
||||
displayText = '自定义时间范围';
|
||||
|
||||
// 计算实际的开始时间和结束时间
|
||||
let startTime, endTime;
|
||||
|
||||
if (state.customStartTime && state.customEndTime) {
|
||||
// 使用自定义时间范围
|
||||
startTime = new Date(state.customStartTime);
|
||||
endTime = new Date(state.customEndTime);
|
||||
displayText = `${formatTime(state.customStartTime)} 至 ${formatTime(state.customEndTime)}`;
|
||||
} else {
|
||||
// 使用预设时间范围
|
||||
const now = new Date();
|
||||
endTime = now;
|
||||
|
||||
// 根据预设时间范围计算开始时间
|
||||
switch(state.currentTimeRange) {
|
||||
case '30m':
|
||||
startTime = new Date(now.getTime() - 30 * 60 * 1000);
|
||||
displayText = `${formatTime(startTime.toISOString())} 至 ${formatTime(endTime.toISOString())}`;
|
||||
break;
|
||||
case '1h':
|
||||
startTime = new Date(now.getTime() - 60 * 60 * 1000);
|
||||
displayText = `${formatTime(startTime.toISOString())} 至 ${formatTime(endTime.toISOString())}`;
|
||||
break;
|
||||
case '2h':
|
||||
startTime = new Date(now.getTime() - 2 * 60 * 60 * 1000);
|
||||
displayText = `${formatTime(startTime.toISOString())} 至 ${formatTime(endTime.toISOString())}`;
|
||||
break;
|
||||
case '6h':
|
||||
startTime = new Date(now.getTime() - 6 * 60 * 60 * 1000);
|
||||
displayText = `${formatTime(startTime.toISOString())} 至 ${formatTime(endTime.toISOString())}`;
|
||||
break;
|
||||
case '12h':
|
||||
startTime = new Date(now.getTime() - 12 * 60 * 60 * 1000);
|
||||
displayText = `${formatTime(startTime.toISOString())} 至 ${formatTime(endTime.toISOString())}`;
|
||||
break;
|
||||
case '24h':
|
||||
startTime = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
||||
displayText = `${formatTime(startTime.toISOString())} 至 ${formatTime(endTime.toISOString())}`;
|
||||
break;
|
||||
default:
|
||||
displayText = '自定义时间范围';
|
||||
}
|
||||
}
|
||||
|
||||
// 更新所有图表的时间范围显示
|
||||
@@ -2897,11 +2958,15 @@ function initChartTabs() {
|
||||
const activeContainer = document.getElementById(`${tabId}ChartContainer`);
|
||||
if (activeContainer) {
|
||||
activeContainer.classList.remove('hidden');
|
||||
console.log(`Shown chart container: ${tabId}ChartContainer`);
|
||||
} else {
|
||||
console.error(`Chart container not found: ${tabId}ChartContainer`);
|
||||
}
|
||||
|
||||
// 显示/隐藏进程信息和磁盘详细信息
|
||||
// 显示/隐藏进程信息、磁盘详细信息和系统日志
|
||||
const processInfoContainer = document.getElementById('processInfoContainer');
|
||||
const diskDetailsContainer = document.getElementById('diskDetailsContainer');
|
||||
const logInfoContainer = document.getElementById('logInfoContainer');
|
||||
|
||||
// 隐藏所有附加信息容器
|
||||
if (processInfoContainer) {
|
||||
@@ -2910,6 +2975,9 @@ function initChartTabs() {
|
||||
if (diskDetailsContainer) {
|
||||
diskDetailsContainer.classList.add('hidden');
|
||||
}
|
||||
if (logInfoContainer) {
|
||||
logInfoContainer.classList.add('hidden');
|
||||
}
|
||||
|
||||
// 根据选项卡显示相应的附加信息
|
||||
if (tabId === 'cpu') {
|
||||
@@ -2926,6 +2994,13 @@ function initChartTabs() {
|
||||
// 加载磁盘详细信息
|
||||
loadDiskDetails();
|
||||
}
|
||||
} else if (tabId === 'logs') {
|
||||
// 显示系统日志
|
||||
if (logInfoContainer) {
|
||||
logInfoContainer.classList.remove('hidden');
|
||||
// 加载系统日志
|
||||
loadSystemLogs();
|
||||
}
|
||||
}
|
||||
|
||||
// 显示/隐藏网卡选择下拉框
|
||||
@@ -2941,15 +3016,64 @@ function initChartTabs() {
|
||||
});
|
||||
});
|
||||
|
||||
// 初始状态:根据当前选中的选项卡显示/隐藏网卡选择下拉框
|
||||
// 初始状态:根据当前选中的选项卡显示/隐藏网卡选择下拉框和加载数据
|
||||
const activeTab = document.querySelector('.chart-tab.active');
|
||||
const interfaceContainer = document.getElementById('interfaceSelectorContainer');
|
||||
if (activeTab && interfaceContainer) {
|
||||
if (activeTab) {
|
||||
const tabId = activeTab.dataset.tab;
|
||||
if (tabId === 'network' || tabId === 'speed') {
|
||||
interfaceContainer.classList.remove('hidden');
|
||||
|
||||
// 显示当前选中的图表容器
|
||||
const activeContainer = document.getElementById(`${tabId}ChartContainer`);
|
||||
if (activeContainer) {
|
||||
activeContainer.classList.remove('hidden');
|
||||
} else {
|
||||
interfaceContainer.classList.add('hidden');
|
||||
console.error(`Initial chart container not found: ${tabId}ChartContainer`);
|
||||
}
|
||||
|
||||
// 显示/隐藏进程信息、磁盘详细信息和系统日志
|
||||
const processInfoContainer = document.getElementById('processInfoContainer');
|
||||
const diskDetailsContainer = document.getElementById('diskDetailsContainer');
|
||||
const logInfoContainer = document.getElementById('logInfoContainer');
|
||||
|
||||
// 隐藏所有附加信息容器
|
||||
if (processInfoContainer) {
|
||||
processInfoContainer.classList.add('hidden');
|
||||
}
|
||||
if (diskDetailsContainer) {
|
||||
diskDetailsContainer.classList.add('hidden');
|
||||
}
|
||||
if (logInfoContainer) {
|
||||
logInfoContainer.classList.add('hidden');
|
||||
}
|
||||
|
||||
// 根据选项卡显示相应的附加信息
|
||||
if (tabId === 'cpu') {
|
||||
// 显示进程信息
|
||||
if (processInfoContainer) {
|
||||
processInfoContainer.classList.remove('hidden');
|
||||
}
|
||||
loadProcessInfo();
|
||||
} else if (tabId === 'disk') {
|
||||
// 显示磁盘详细信息
|
||||
if (diskDetailsContainer) {
|
||||
diskDetailsContainer.classList.remove('hidden');
|
||||
}
|
||||
loadDiskDetails();
|
||||
} else if (tabId === 'logs') {
|
||||
// 显示系统日志
|
||||
if (logInfoContainer) {
|
||||
logInfoContainer.classList.remove('hidden');
|
||||
}
|
||||
loadSystemLogs();
|
||||
}
|
||||
|
||||
// 显示/隐藏网卡选择下拉框
|
||||
if (interfaceContainer) {
|
||||
if (tabId === 'network' || tabId === 'speed') {
|
||||
interfaceContainer.classList.remove('hidden');
|
||||
} else {
|
||||
interfaceContainer.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2974,7 +3098,18 @@ let processPagination = {
|
||||
itemsPerPage: 5,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
allProcesses: []
|
||||
allProcesses: [],
|
||||
lastDeviceID: '' // 上次请求数据的设备ID
|
||||
};
|
||||
|
||||
// 系统日志分页状态
|
||||
let logPagination = {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 5,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
allLogs: [],
|
||||
lastDeviceID: '' // 上次请求数据的设备ID
|
||||
};
|
||||
|
||||
// 加载进程信息
|
||||
@@ -2991,7 +3126,16 @@ async function loadProcessInfo(page = 1) {
|
||||
params.append('device_id', state.currentDeviceID);
|
||||
}
|
||||
|
||||
// 如果是第一次加载,获取全部数据
|
||||
// 检查设备ID是否变化
|
||||
if (processPagination.lastDeviceID !== state.currentDeviceID) {
|
||||
// 设备ID变化,清空旧数据
|
||||
processPagination.allProcesses = [];
|
||||
processPagination.totalItems = 0;
|
||||
processPagination.totalPages = 0;
|
||||
processPagination.currentPage = 1;
|
||||
}
|
||||
|
||||
// 如果是第一次加载或设备ID变化,获取全部数据
|
||||
if (processPagination.allProcesses.length === 0) {
|
||||
// 发送请求
|
||||
const response = await fetch(`${API_BASE_URL}/metrics/processes?${params.toString()}`);
|
||||
@@ -3003,6 +3147,8 @@ async function loadProcessInfo(page = 1) {
|
||||
processPagination.allProcesses = data.data || [];
|
||||
processPagination.totalItems = processPagination.allProcesses.length;
|
||||
processPagination.totalPages = Math.ceil(processPagination.totalItems / processPagination.itemsPerPage);
|
||||
// 更新上次请求数据的设备ID
|
||||
processPagination.lastDeviceID = state.currentDeviceID;
|
||||
}
|
||||
|
||||
// 更新当前页码
|
||||
@@ -3072,7 +3218,8 @@ let diskPagination = {
|
||||
itemsPerPage: 5,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
allDisks: []
|
||||
allDisks: [],
|
||||
lastDeviceID: '' // 上次请求数据的设备ID
|
||||
};
|
||||
|
||||
// 创建分页控件
|
||||
@@ -3221,7 +3368,16 @@ async function loadDiskDetails(page = 1) {
|
||||
params.append('device_id', state.currentDeviceID);
|
||||
}
|
||||
|
||||
// 如果是第一次加载,获取全部数据
|
||||
// 检查设备ID是否变化
|
||||
if (diskPagination.lastDeviceID !== state.currentDeviceID) {
|
||||
// 设备ID变化,清空旧数据
|
||||
diskPagination.allDisks = [];
|
||||
diskPagination.totalItems = 0;
|
||||
diskPagination.totalPages = 0;
|
||||
diskPagination.currentPage = 1;
|
||||
}
|
||||
|
||||
// 如果是第一次加载或设备ID变化,获取全部数据
|
||||
if (diskPagination.allDisks.length === 0) {
|
||||
// 发送请求
|
||||
const response = await fetch(`${API_BASE_URL}/metrics/disk_details?${params.toString()}`);
|
||||
@@ -3233,6 +3389,8 @@ async function loadDiskDetails(page = 1) {
|
||||
diskPagination.allDisks = data.data || [];
|
||||
diskPagination.totalItems = diskPagination.allDisks.length;
|
||||
diskPagination.totalPages = Math.ceil(diskPagination.totalItems / diskPagination.itemsPerPage);
|
||||
// 更新上次请求数据的设备ID
|
||||
diskPagination.lastDeviceID = state.currentDeviceID;
|
||||
}
|
||||
|
||||
// 更新当前页码
|
||||
@@ -3319,9 +3477,15 @@ async function loadDiskDetails(page = 1) {
|
||||
}
|
||||
|
||||
// 加载系统日志
|
||||
async function loadSystemLogs() {
|
||||
async function loadSystemLogs(page = 1) {
|
||||
console.log('loadSystemLogs function called');
|
||||
const logTableBody = document.getElementById('logTableBody');
|
||||
if (!logTableBody) return;
|
||||
const logPaginationContainer = document.getElementById('logPaginationContainer');
|
||||
|
||||
if (!logTableBody) {
|
||||
console.error('logTableBody element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建查询参数
|
||||
@@ -3330,46 +3494,86 @@ async function loadSystemLogs() {
|
||||
params.append('device_id', state.currentDeviceID);
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
const response = await fetch(`${API_BASE_URL}/metrics/logs?${params.toString()}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch system logs');
|
||||
// 检查设备ID是否变化
|
||||
if (logPagination.lastDeviceID !== state.currentDeviceID) {
|
||||
// 设备ID变化,清空旧数据
|
||||
logPagination.allLogs = [];
|
||||
logPagination.totalItems = 0;
|
||||
logPagination.totalPages = 0;
|
||||
logPagination.currentPage = 1;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const logs = data.data;
|
||||
// 如果是第一次加载或设备ID变化,获取全部数据
|
||||
if (logPagination.allLogs.length === 0) {
|
||||
console.log('Fetching logs from:', `${API_BASE_URL}/metrics/logs?${params.toString()}`);
|
||||
// 发送请求
|
||||
const response = await fetch(`${API_BASE_URL}/metrics/logs?${params.toString()}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
logPagination.allLogs = data.data || [];
|
||||
logPagination.totalItems = logPagination.allLogs.length;
|
||||
logPagination.totalPages = Math.ceil(logPagination.totalItems / logPagination.itemsPerPage);
|
||||
// 更新上次请求数据的设备ID
|
||||
logPagination.lastDeviceID = state.currentDeviceID;
|
||||
}
|
||||
|
||||
// 更新当前页码
|
||||
logPagination.currentPage = page;
|
||||
|
||||
// 清空表格
|
||||
logTableBody.innerHTML = '';
|
||||
|
||||
if (logs.length === 0) {
|
||||
if (logPagination.totalItems === 0) {
|
||||
// 没有日志数据,显示提示
|
||||
logTableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="4" class="px-6 py-4 text-center text-gray-500">暂无系统日志</td>
|
||||
</tr>
|
||||
`;
|
||||
|
||||
// 隐藏分页控件
|
||||
if (logPaginationContainer) {
|
||||
logPaginationContainer.innerHTML = '';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算分页数据
|
||||
const startIndex = (logPagination.currentPage - 1) * logPagination.itemsPerPage;
|
||||
const endIndex = Math.min(startIndex + logPagination.itemsPerPage, logPagination.totalItems);
|
||||
const paginatedLogs = logPagination.allLogs.slice(startIndex, endIndex);
|
||||
|
||||
// 填充表格数据
|
||||
logs.forEach((log, index) => {
|
||||
paginatedLogs.forEach((log, index) => {
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${index + 1}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${startIndex + index + 1}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 font-medium">${log.source || 'System'}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${log.time || new Date().toLocaleString()}</td>
|
||||
<td class="px-6 py-4 whitespace-normal text-sm text-gray-500">${log.message || 'No message'}</td>
|
||||
`;
|
||||
logTableBody.appendChild(row);
|
||||
});
|
||||
|
||||
// 创建分页控件
|
||||
if (logPaginationContainer) {
|
||||
createPaginationControls(logPaginationContainer, logPagination, loadSystemLogs);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading system logs:', error);
|
||||
logTableBody.innerHTML = `
|
||||
<tr>
|
||||
<td colspan="4" class="px-6 py-4 text-center text-red-500">加载系统日志失败</td>
|
||||
<td colspan="4" class="px-6 py-4 text-center text-red-500">加载系统日志失败: ${error.message}</td>
|
||||
</tr>
|
||||
`;
|
||||
|
||||
if (logPaginationContainer) {
|
||||
logPaginationContainer.innerHTML = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3379,11 +3583,56 @@ function handleHashChange() {
|
||||
if (hash === '#serverMonitor' || hash.startsWith('#serverMonitor/')) {
|
||||
// 延迟一下,确保DOM已经渲染完成
|
||||
setTimeout(() => {
|
||||
loadMetrics();
|
||||
// 加载进程信息(如果当前是CPU选项卡)
|
||||
// 加载当前选项卡对应的数据
|
||||
const activeTab = document.querySelector('.chart-tab.active');
|
||||
if (activeTab && activeTab.dataset.tab === 'cpu') {
|
||||
loadProcessInfo();
|
||||
if (activeTab) {
|
||||
const tabId = activeTab.dataset.tab;
|
||||
|
||||
// 显示/隐藏附加信息容器
|
||||
const processInfoContainer = document.getElementById('processInfoContainer');
|
||||
const diskDetailsContainer = document.getElementById('diskDetailsContainer');
|
||||
const logInfoContainer = document.getElementById('logInfoContainer');
|
||||
|
||||
// 隐藏所有附加信息容器
|
||||
if (processInfoContainer) {
|
||||
processInfoContainer.classList.add('hidden');
|
||||
}
|
||||
if (diskDetailsContainer) {
|
||||
diskDetailsContainer.classList.add('hidden');
|
||||
}
|
||||
if (logInfoContainer) {
|
||||
logInfoContainer.classList.add('hidden');
|
||||
}
|
||||
|
||||
if (tabId === 'logs') {
|
||||
// 显示系统日志
|
||||
if (logInfoContainer) {
|
||||
logInfoContainer.classList.remove('hidden');
|
||||
}
|
||||
// 加载系统日志
|
||||
loadSystemLogs();
|
||||
} else {
|
||||
// 加载其他监控数据
|
||||
loadMetrics();
|
||||
|
||||
// 根据选项卡加载附加信息
|
||||
if (tabId === 'cpu') {
|
||||
// 显示进程信息
|
||||
if (processInfoContainer) {
|
||||
processInfoContainer.classList.remove('hidden');
|
||||
}
|
||||
loadProcessInfo();
|
||||
} else if (tabId === 'disk') {
|
||||
// 显示磁盘详细信息
|
||||
if (diskDetailsContainer) {
|
||||
diskDetailsContainer.classList.remove('hidden');
|
||||
}
|
||||
loadDiskDetails();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果没有找到激活的选项卡,默认加载metrics
|
||||
loadMetrics();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user