diff --git a/client.py b/client.py index e18f25a..42a731b 100644 --- a/client.py +++ b/client.py @@ -112,8 +112,8 @@ def get_memory_info(error_dict): result_dict = dict() try: mem = psutil.virtual_memory() - result_dict["total"] = mem.total - result_dict["used"] = mem.used + result_dict["total"] = mem.total / 1024 + result_dict["used"] = mem.used / 1024 except Exception as e: error_dict['memory'] = e diff --git a/web/css/style_1.css b/web/css/style_1.css new file mode 100644 index 0000000..9d8698e --- /dev/null +++ b/web/css/style_1.css @@ -0,0 +1,58 @@ +#header-container { + background-color: beige; +} + +.card { + border-style: solid; + border-width: 2px; + border-color: black; + /* background-color: aqua; */ + padding: 5px; + margin: 5px; + border-radius: 8px; +} + +.server-name { + background-color: black; + color: white; + border-radius: 8px; + padding: 4px 10px; + font-size: 26px; +} + +.gpu-info { + /* background-color: aqua; */ + border-style: solid; + border-width: 1px; + border-color: #ccc; + border-radius: 8px; + margin-top: 5px; + padding: 4px 8px; + margin-bottom: 5px; + background-color: #f9f9f9; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} + +.process-item { + color: rgb(26, 92, 247); + font-weight: bold; +} + +/*占用状态*/ +.state-free { + color: green; +} +.state-occupy { + color: red; +} +.state-light-occupy { + color: orange; +} +.state-super-occupy { + color: rgb(255, 0, 0); + font-weight: bold; + font-size: 20px; + background-color: rgb(255, 255, 0); + border-radius: 8px; + padding: 1px 6px; +} \ No newline at end of file diff --git a/web/index.html b/web/index.html index 2b89fbf..32e0425 100644 --- a/web/index.html +++ b/web/index.html @@ -4,8 +4,15 @@ 服务器信息 + - +
+ 服务器信息 +
+
+
+ + \ No newline at end of file diff --git a/web/js/script.js b/web/js/script.js new file mode 100644 index 0000000..04aef12 --- /dev/null +++ b/web/js/script.js @@ -0,0 +1,180 @@ +// 请求服务器获取数据 +function fetchData() { + fetch('http://127.0.0.1:15002/api/get_data') + // 获取服务器和显卡数据 + .then(response => response.json()) // 解析 JSON 响应 + .then(data => { + // 处理 JSON 数据 + // console.log(data); + displayServerData(data); // 调用显示数据的函数 + }) + .catch(error => { + // console.error('Error fetching data:', error); + displayError(error + " (多半是没有正确连接服务器端,可能是没开、网络错误)"); + }); +} + +// 显示错误 +function displayError(err_info){ + let serverDataContainer = document.getElementById('server-data'); + serverDataContainer.innerHTML = ''; // 清空容器 + + let errDiv = document.createElement('div'); + errDiv.classList.add('error-info'); + errDiv.innerText = err_info; + serverDataContainer.appendChild(errDiv); +} + +// 将KB转为合适的格式 +function parse_data_unit(num, fixedLen=2){ + if (num < 1024){ + return num.toFixed(fixedLen) + " KB"; + } + + num /= 1024; + if (num < 1024){ + return num.toFixed(fixedLen) + " MB"; + } + + num /= 1024; + if (num < 1024){ + return num.toFixed(fixedLen) + " GB"; + } + + num /= 1024; + if (num < 1024){ + return num.toFixed(fixedLen) + " TB"; + } +} + + +function add_bar(serverCard){ + let bar = document.createElement('hr'); + serverCard.appendChild(bar); +} + +// 添加服务器信息的元素 +function displayServerData(data){ + let serverDataContainer = document.getElementById('server-data'); + serverDataContainer.innerHTML = ''; // 清空容器 + + let serverDataDict = data['server_dict']; + + // 创建每一个服务器的信息 + for (let serverTitle in serverDataDict){ + let serverCard = document.createElement('div'); + serverCard.className = 'card'; + + // 标题 + let serverName = document.createElement('div'); + serverName.className = 'server-name'; + serverName.textContent = serverTitle; + serverCard.appendChild(serverName); + + serverData = serverDataDict[serverTitle]; + // 如果没有数据则跳过 + if (serverData == null){ + let errText = document.createElement('div'); + errText.className = 'error-text'; + errText.textContent = "No data."; + serverCard.appendChild(errText); + serverDataContainer.appendChild(serverCard); + continue; + } + + // 内存 + if ('memory' in serverData){ + let memoryInfo = document.createElement('div'); + memoryInfo.className = 'memory-info'; + let totalNum = serverData.memory.total + let usedNum = serverData.memory.used + let totalMem = parse_data_unit(totalNum); + let usedMem = parse_data_unit(usedNum); + let tmpClass = "state-free"; + if (usedNum / totalNum > 0.95) + tmpClass = "state-super-occupy"; + else if (usedNum / totalNum > 0.8) + tmpClass = "state-occupy"; + else if (usedNum / totalNum > 0.6) + tmpClass = "state-light-occupy"; + memoryInfo.innerHTML += " 内存 : " + usedMem + " / " + totalMem + "
"; + serverCard.appendChild(memoryInfo); + // 分割线 + add_bar(serverCard); + } + + // 存储空间 + if ('storage_list' in serverData){ + let storageInfo = document.createElement('div'); + storageInfo.className = 'storage-info'; + + for (let i = 0; i < serverData.storage_list.length; i++) { + let targetPath = serverData.storage_list[i].path; + let totalNum = serverData.storage_list[i].total + let availableNum = serverData.storage_list[i].available + let totalStorage = parse_data_unit(totalNum); + let availableStorage = parse_data_unit(totalNum - availableNum); + let tmpClass = "state-free"; + if (availableNum / totalNum < 0.01) + tmpClass = "state-super-occupy"; + else if (availableNum / totalNum < 0.1) + tmpClass = "state-occupy"; + else if (availableNum / totalNum < 0.3) + tmpClass = "state-light-occupy"; + storageInfo.innerHTML += '' + targetPath + " : " + availableStorage + " / " + totalStorage + "
"; + } + + serverCard.appendChild(storageInfo); + // 分割线 + add_bar(serverCard); + } + + if ('gpu_list' in serverData){ + serverData.gpu_list.forEach(function(gpu){ + let gpuInfo = document.createElement('div'); + gpuInfo.className = 'gpu-info'; + + let markFree = ' 空闲'; + let markLightOccupy = ' 占用'; + let markOccupy = ' 占用'; + let tmpMark = markFree; + if (gpu.used_memory < 1000 && gpu.utilization < 20){ + tmpMark = markFree; + } + else if (gpu.util_mem < 50){ + tmpMark = markLightOccupy; + }else{ + tmpMark = markOccupy; + } + gpuInfo.innerHTML = '' + gpu.idx + ' - ' + gpu.name + tmpMark + '
' + + '温度: ' + gpu.temperature + '°C
' + + '显存: ' + gpu.used_memory + ' / ' + gpu.total_memory + " MB" + '
' + + '利用率: ' + gpu.utilization + '%'; + + // 添加进程信息 + let processInfo = document.createElement('div'); + processInfo.classList.add('process-info'); + processInfo.innerHTML = "使用情况:"; + + gpu.process_list.sort((a, b) => b.memory - a.memory); + gpu.process_list.forEach(function(item, index){ + console.log(item.memory ); + if (item.memory > 40) + processInfo.innerHTML += `${item.user} (${item.memory}) `; + }); + gpuInfo.appendChild(processInfo); // 将用户信息添加到GPU信息中 + + serverCard.appendChild(gpuInfo); + }); + // 分割线 + add_bar(serverCard); + } + + // 单个服务器信息作为child加入 + serverDataContainer.appendChild(serverCard); + } +} + +// TODO test +fetchData() \ No newline at end of file