// 在文件开头添加调试日志 console.log('monitor.js 加载完成'); // 全局变量声明 let currentDirectory = null; let selectedPid = null; let updateInterval = null; let cpuChart = null; let memoryChart = null; let gpuChart = null; // 更新监控数据 function updateMonitorData(pid) { // 使用保存的监控类型 const type = currentMonitorType; console.log('正在更新数据,类型:', type); // 调试日志 // 构建 URL,确保包含 type 参数 const url = new URL(`${window.location.origin}/api/process/${pid}/status/`); url.searchParams.append('type', type); console.log('请求 URL:', url.toString()); // 调试日志 fetch(url) .then(response => response.json()) .then(response => { if (response.status === 'success') { const data = response.data; updateUI(data, type); } }) .catch(error => handleError(error, '获取监控数据失败')); } // 获取所有监控按钮和停止按钮 const monitorButtons = document.querySelectorAll('[data-type]'); const stopBtn = document.getElementById('stopMonitor'); const pidInput = document.getElementById('pidInput'); // 保存当前监控类型的全局变量 let currentMonitorType = null; // 开始监控 function startMonitoring(pid) { console.log('开始监控,类型:', currentMonitorType); // 调试日志 updateMonitorData(pid); // 立即执行一次更新 monitorInterval = setInterval(() => { updateMonitorData(pid); }, 60000); } // 停止监控 function stopMonitoring() { if (!currentDirectory) { console.error('没有正在监控的目录'); showMessage('没有正在监控的目录', 'error'); return; } const stopBtn = document.getElementById('stopDirectoryMonitor'); if (!stopBtn) return; stopBtn.disabled = true; stopBtn.textContent = '正在停止...'; // 先清理定时器 if (updateInterval) { clearInterval(updateInterval); updateInterval = null; } const directoryToStop = currentDirectory; fetch('/monitor/stop-directory-monitor/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCSRFToken(), }, body: JSON.stringify({ directory: directoryToStop }) }) .then(response => response.json()) .then(data => { if (data.status === 'success') { cleanupMonitoringState(); showMessage('监控已停止', 'success'); } else { throw new Error(data.message || '停止监控失败'); } }) .catch(error => { console.error('停止监控失败:', error); showMessage(error.message || '停止监控失败', 'error'); stopBtn.disabled = false; }) .finally(() => { stopBtn.textContent = '停止监控'; }); } // 初始化图表 function initCharts() { console.log('初始化图表'); cpuChart = echarts.init(document.getElementById('cpuChart')); memoryChart = echarts.init(document.getElementById('memoryChart')); gpuChart = echarts.init(document.getElementById('gpuChart')); const baseOption = { tooltip: { trigger: 'axis', formatter: function(params) { const time = new Date(params[0].value[0]).toLocaleTimeString(); return `${time}
${params[0].seriesName}: ${params[0].value[1].toFixed(2)}%`; } }, xAxis: { type: 'time', splitLine: { show: false } }, yAxis: { type: 'value', min: 0, max: 100, splitLine: { show: true } }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, series: [{ type: 'line', showSymbol: false, data: [], smooth: true, areaStyle: { opacity: 0.1 } }] }; cpuChart.setOption({ ...baseOption, series: [{ ...baseOption.series[0], name: 'CPU使用率', itemStyle: { color: '#2196F3' } }] }); memoryChart.setOption({ ...baseOption, series: [{ ...baseOption.series[0], name: '内存使用量', itemStyle: { color: '#4CAF50' } }] }); gpuChart.setOption({ ...baseOption, series: [{ ...baseOption.series[0], name: 'GPU使用率', itemStyle: { color: '#FF5722' } }] }); } // 更新图表数据 function updateCharts(process) { console.log('更新图表:', process); const now = new Date(); // 更新CPU图表 if (cpuChart) { updateChartData(cpuChart, now, process.cpu_usage); } // 更新内存图表 if (memoryChart) { updateChartData(memoryChart, now, process.memory_usage); } // 更新GPU图表 if (gpuChart && process.gpu_info) { updateChartData(gpuChart, now, process.gpu_info.usage); } } // 辅助函数:更新图表数据 function updateChartData(chart, time, value) { if (!chart) return; try { const option = chart.getOption(); const data = option.series[0].data || []; data.push([time, value]); // 保持最近60个数据点 if (data.length > 60) { data.shift(); } chart.setOption({ series: [{ data: data }] }); } catch (error) { console.error('更新图表数据失败:', error); } } // 修改更新进程表格函数 function updateProcessTable(processes) { console.log('更新进程表格:', processes); // 调试日志 const table = document.getElementById('processTable'); if (!table) { console.error('找不到进程表格元素'); return; } if (!processes || processes.length === 0) { table.innerHTML = ` 暂无进程数据 `; return; } table.innerHTML = processes.map(proc => ` ${proc.pid} ${proc.name}
${proc.cpu_usage.toFixed(1)}%
${proc.memory_usage.toFixed(1)} MB
${proc.gpu_info.usage}%
${proc.gpu_info.memory.toFixed(1)} MB 运行中 `).join(''); } // 修改选择进程的函数 function selectProcess(pid) { console.log('选择进程:', pid); selectedPid = pid.toString(); // 确保转换为字符串 // 更新选择器 const selector = document.getElementById('processSelector'); if (selector) { selector.value = selectedPid; } // 更新表格中的选中状态 const rows = document.querySelectorAll('#processTable tr'); rows.forEach(row => { if (row.cells && row.cells[0] && row.cells[0].textContent === selectedPid) { row.classList.add('table-primary'); } else { row.classList.remove('table-primary'); } }); // 获取最新数据并更新图表 if (currentDirectory) { fetch(`/monitor/directory-status/?directory=${encodeURIComponent(currentDirectory)}`) .then(response => response.json()) .then(data => { if (data.status === 'success' && data.processes) { const selectedProcess = data.processes.find(p => p.pid.toString() === selectedPid); if (selectedProcess) { // 更新图表 updateCharts(selectedProcess); // 更新详细信息 updateProcessDetails(selectedProcess); } } }) .catch(error => console.error('获取进程详情失败:', error)); } } // 修改进程选择器更新函数 function updateProcessSelector(processes) { console.log('更新进程选择器,进程列表:', processes); // 调试日志 const selector = document.getElementById('processSelector'); const processInfo = document.getElementById('selectedProcessInfo'); if (!selector) { console.error('找不到进程选择器元素'); return; } // 启用选择器 selector.disabled = false; // 获取当前的进程列表 const currentPids = processes.map(p => p.pid.toString()); console.log('当前PID列表:', currentPids); // 调试日志 // 如果当前选中的进程不在列表中,清除选择 if (selectedPid && !currentPids.includes(selectedPid.toString())) { console.log('选中的进程不再存在,清除选择'); // 调试日志 selectedPid = null; clearCharts(); } // 移除旧的事件监听器 const newSelector = selector.cloneNode(true); selector.parentNode.replaceChild(newSelector, selector); // 更新选择器选项 newSelector.innerHTML = ` ${processes.map(proc => ` `).join('')} `; // 添加新的事件监听器 newSelector.addEventListener('change', function() { console.log('进程选择变更:', this.value); selectedPid = this.value; if (selectedPid) { const selected = processes.find(p => p.pid === parseInt(selectedPid)); if (selected) { processInfo.textContent = `监控中: PID ${selected.pid} - ${selected.name}`; updateProcessDetails(selected); // 更新详细信息 clearCharts(); } } else { processInfo.textContent = '未选择进程'; clearCharts(); // 清空详细信息 ['basicInfo', 'resourceInfo', 'networkInfo', 'fileInfo'].forEach(id => { document.getElementById(id).innerHTML = '

选择进程查看详细信息

'; }); } }); console.log('进程选择器更新完成'); // 调试日志 } // 添加清除图表数据函数 function clearCharts() { const emptyOption = { series: [{ data: [] }] }; cpuChart.setOption(emptyOption); memoryChart.setOption(emptyOption); gpuChart.setOption(emptyOption); } document.addEventListener('DOMContentLoaded', function() { console.log('DOM加载完成,开始初始化'); const startBtn = document.getElementById('startDirectoryMonitor'); const stopBtn = document.getElementById('stopDirectoryMonitor'); if (!startBtn || !stopBtn) { console.error('找不到监控按钮元素'); return; } // 初始化图表 initCharts(); // 开始监控按钮事件 startBtn.addEventListener('click', function() { console.log('点击了开始监控按钮'); const directory = document.getElementById('directoryInput').value; const statusDiv = document.getElementById('directoryMonitorStatus'); if (!directory) { statusDiv.style.display = 'block'; statusDiv.className = 'alert alert-warning'; statusDiv.textContent = '请输入目录路径'; return; } // 显示加载状态 startBtn.disabled = true; startBtn.textContent = '启动中...'; statusDiv.style.display = 'block'; statusDiv.className = 'alert alert-info'; statusDiv.textContent = '正在启动监控...'; console.log('开始监控目录:', directory); // 清除旧的选择 selectedPid = null; clearCharts(); fetch('/monitor/scan-directory/', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ directory: directory }) }) .then(response => response.json()) .then(data => { console.log('接口返回:', data); if (data.status === 'success') { currentDirectory = directory; statusDiv.className = 'alert alert-success'; statusDiv.textContent = data.message; startBtn.disabled = true; stopBtn.disabled = false; // 开始定期获取详细信息 if (updateInterval) { clearInterval(updateInterval); } currentDirectory = directory; getProcessDetails(directory); // 立即获取一次 updateInterval = setInterval(() => getProcessDetails(directory), 5000); // 每5秒更新一次 } else { statusDiv.className = 'alert alert-danger'; statusDiv.textContent = data.message; startBtn.disabled = false; } }) .catch(error => { console.error('监控启动失败:', error); statusDiv.className = 'alert alert-danger'; statusDiv.textContent = '启动监控失败: ' + error.message; startBtn.disabled = false; }) .finally(() => { startBtn.textContent = '开始监控'; }); }); // 停止监控按钮事件 if (stopBtn) { stopBtn.addEventListener('click', function() { console.log('停止监控,当前目录:', currentDirectory); // 检查是否有当前目录 if (!currentDirectory) { console.error('没有正在监控的目录'); showMessage('没有正在监控的目录', 'error'); return; } // 禁用按钮,防止重复点击 stopBtn.disabled = true; stopBtn.textContent = '正在停止...'; // 先清理定时器,防止继续发送请求 if (updateInterval) { clearInterval(updateInterval); updateInterval = null; } // 保存当前目录的副本 const directoryToStop = currentDirectory; // 发送停止监控请求到服务器 fetch('/monitor/stop-directory-monitor/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCSRFToken(), }, body: JSON.stringify({ directory: directoryToStop, timestamp: new Date().getTime() // 添加时间戳防止缓存 }) }) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { console.log('停止监控响应:', data); if (data.status === 'success') { // 清理前端状态 cleanupMonitoringState(); // 显示成功消息 showMessage('监控已停止', 'success'); } else { throw new Error(data.message || '停止监控失败'); } }) .catch(error => { console.error('停止监控失败:', error); showMessage(error.message || '停止监控请求失败', 'error'); // 恢复按钮状态 stopBtn.disabled = false; stopBtn.textContent = '停止监控'; }); }); } // 初始状态设置 stopBtn.disabled = true; // 初始状态下停止按钮禁用 console.log('初始化完成'); // 为每个监控按钮添加点击事件 monitorButtons.forEach(button => { button.addEventListener('click', function() { const pid = pidInput.value.trim(); const type = this.dataset.type; // 从按钮的 data-type 属性获取类型 if (!pid) { alert('请输入进程ID'); return; } // 保存当前选择的监控类型 currentMonitorType = type; console.log('设置监控类型为:', currentMonitorType); fetch(`/monitor/start/?pid=${pid}&type=${type}`) .then(response => response.json()) .then(data => { if (data.status === 'success') { startMonitoring(pid); // 禁用所有监控按钮 monitorButtons.forEach(btn => btn.disabled = true); stopBtn.disabled = false; pidInput.disabled = true; } else { alert(data.message); } }) .catch(error => { console.error('启动监控失败:', error); alert('启动监控失败'); }); }); }); // 获取自动检测按钮 const startAutoDetectBtn = document.getElementById('startAutoDetectBtn'); const stopAutoDetectBtn = document.getElementById('stopAutoDetectBtn'); // 获取CSRF Token function getCSRFToken() { const name = 'csrftoken'; let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // 添加自动检测开始按钮事件 startAutoDetectBtn.addEventListener('click', function() { fetch('/auto_detect/', { method: 'POST', headers: { 'X-CSRFToken': getCSRFToken(), 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.status === 'success') { alert('已开始自动检测高资源进程'); startAutoDetectBtn.disabled = true; stopAutoDetectBtn.disabled = false; } else { alert(data.message); } }) .catch(error => { console.error('启动自动检测失败:', error); alert('启动自动检测失败'); }); }); // 添加自动检测停止按钮事件 stopAutoDetectBtn.addEventListener('click', function() { fetch('/stop_auto_detect/', { method: 'POST', headers: { 'X-CSRFToken': getCSRFToken(), 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { if (data.status === 'success') { alert('已停止自动检测'); startAutoDetectBtn.disabled = false; stopAutoDetectBtn.disabled = true; } else { alert(data.message); } }) .catch(error => { console.error('停止自动检测失败:', error); alert('停止自动检测失败'); }); }); }); // 更新 UI 的函数 function updateUI(data, type) { // 根据监控类型更新对应的表格 if (type === 'all' || type === 'cpu') { document.getElementById('cpuTable').innerHTML = ` 使用率${data.cpu.usage} 用户态时间${data.cpu.user_time} 内核态时间${data.cpu.system_time} CPU核心数${data.cpu.cores} CPU频率${data.cpu.frequency} 上下文切换${data.cpu.context_switches} `; document.getElementById('cpuStatus').className = 'badge bg-success status-badge'; document.getElementById('cpuStatus').textContent = '监控中'; } if (type === 'all' || type === 'memory') { document.getElementById('memoryTable').innerHTML = ` 物理内存${data.memory.physical} 虚拟内存${data.memory.virtual} 内存映射${data.memory.mappings} 系统内存使用${data.memory.system_usage} 交换空间使用${data.memory.swap_usage} `; document.getElementById('memoryStatus').className = 'badge bg-success status-badge'; document.getElementById('memoryStatus').textContent = '监控中'; } if (type === 'all' || type === 'gpu') { document.getElementById('gpuTable').innerHTML = ` 使用率${data.gpu.usage} 显存使用${data.gpu.memory} `; document.getElementById('gpuStatus').className = 'badge bg-success status-badge'; document.getElementById('gpuStatus').textContent = '监控中'; } // 更新最后更新时间 document.getElementById('lastUpdate').textContent = `最后更新: ${data.timestamp}`; } // 添加错误处理函数 function handleError(error, message) { console.error(message, error); ['cpu', 'gpu', 'memory'].forEach(type => { const statusElement = document.getElementById(`${type}Status`); if (statusElement) { statusElement.className = 'badge bg-danger status-badge'; statusElement.textContent = '错误'; } }); alert(message); } // 窗口大小改变时调整图表大小 window.addEventListener('resize', function() { if (cpuChart) cpuChart.resize(); if (memoryChart) memoryChart.resize(); if (gpuChart) gpuChart.resize(); }); // 更新进程详细信息的函数 function updateProcessDetails(process) { if (!process) return; // 检查元素是否存在 const basicInfo = document.getElementById('basicInfo'); const resourceInfo = document.getElementById('resourceInfo'); if (!basicInfo || !resourceInfo) { console.error('找不到详情显示元素'); return; } try { // 更新基本信息 basicInfo.innerHTML = `
PID
${process.pid}
进程名
${process.name}
命令行
${process.command_line}
工作目录
${process.working_directory}
创建时间
${process.create_time}
`; // 更新资源信息 resourceInfo.innerHTML = `
CPU使用率
${process.cpu_usage.toFixed(2)}%
内存使用
${process.memory_usage.toFixed(2)} MB
线程数
${process.threads}
GPU使用率
${process.gpu_info.usage}%
GPU内存
${process.gpu_info.memory.toFixed(2)} MB
`; } catch (error) { console.error('更新进程详情失败:', error); } } // 修改定期更新函数 function startPeriodicUpdate(directory) { console.log('开始定期更新, 目录:', directory); if (updateInterval) { clearInterval(updateInterval); } // 立即执行一次更新 getProcessDetails(directory); // 设置定时更新 updateInterval = setInterval(() => { getProcessDetails(directory); }, 5000); } // 修改获取进程详情的函数 function getProcessDetails(directory) { if (!directory || !currentDirectory) { // 添加currentDirectory检查 console.log('没有目录或已停止监控'); return; } // 使用 AbortController 来控制fetch请求 if (window.currentFetch) { window.currentFetch.abort(); } window.currentFetch = new AbortController(); fetch(`/monitor/directory-status/?directory=${encodeURIComponent(directory)}`, { signal: window.currentFetch.signal }) .then(response => response.json()) .then(data => { if (!currentDirectory) { // 再次检查是否已停止监控 console.log('监控已停止,不更新数据'); return; } console.log('收到进程数据:', data); if (data.status === 'success' && data.processes && data.processes.length > 0) { updateProcessTable(data.processes); if (selectedPid) { const selectedProcess = data.processes.find(p => p.pid.toString() === selectedPid); if (selectedProcess) { updateCharts(selectedProcess); updateProcessDetails(selectedProcess); } } } }) .catch(error => { if (error.name === 'AbortError') { console.log('请求被中止'); } else { console.error('获取进程详情失败:', error); } }); } // 获取所有正在监控的进程ID function getAllMonitoredPids() { const table = document.getElementById('processTable'); if (!table) return []; const pids = []; const rows = table.getElementsByTagName('tr'); for (let row of rows) { const firstCell = row.cells[0]; if (firstCell && !isNaN(firstCell.textContent)) { pids.push(firstCell.textContent); } } return pids; } // 修改清理监控状态的函数 function cleanupMonitoringState() { console.log('清理监控状态'); // 先取消所有正在进行的请求 if (window.currentFetch) { window.currentFetch.abort(); window.currentFetch = null; } // 清除定时器 if (updateInterval) { clearInterval(updateInterval); updateInterval = null; } // 清除状态变量(在清理完其他内容后再清除) const oldDirectory = currentDirectory; currentDirectory = null; selectedPid = null; console.log('已清除的目录:', oldDirectory); // 清空图表 clearCharts(); // 清空进程列表 const processTable = document.getElementById('processTable'); if (processTable) { processTable.innerHTML = ` 未开始监控 `; } // 清空详细信息 const basicInfo = document.getElementById('basicInfo'); const resourceInfo = document.getElementById('resourceInfo'); if (basicInfo) { basicInfo.innerHTML = '

未选择进程

'; } if (resourceInfo) { resourceInfo.innerHTML = '

未选择进程

'; } // 更新按钮状态 const startBtn = document.getElementById('startDirectoryMonitor'); const stopBtn = document.getElementById('stopDirectoryMonitor'); if (startBtn) startBtn.disabled = false; if (stopBtn) { stopBtn.disabled = true; stopBtn.textContent = '停止监控'; } } // 添加显示消息的函数 function showMessage(message, type = 'info') { const statusDiv = document.getElementById('directoryMonitorStatus'); if (statusDiv) { statusDiv.style.display = 'block'; statusDiv.className = `alert alert-${type}`; statusDiv.textContent = message; // 3秒后自动隐藏 setTimeout(() => { statusDiv.style.display = 'none'; }, 3000); } }