4 changed files with 248 additions and 3 deletions
@ -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; |
|||
} |
@ -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 += "<strong> 内存 : </strong> <span class=\"" + tmpClass + "\">" + usedMem + " / " + totalMem + "</span><br>"; |
|||
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 += '<strong>' + targetPath + " :</strong> <span class=\"" + tmpClass |
|||
+ "\">" + availableStorage + " / " + totalStorage + "</span><br>"; |
|||
} |
|||
|
|||
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 = '<span class="state-free"> 空闲</span>'; |
|||
let markLightOccupy = '<span class="state-light-occupy"> 占用</span>'; |
|||
let markOccupy = '<span class="state-occupy"> 占用</span>'; |
|||
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 = '<strong>' + gpu.idx + ' - ' + gpu.name + tmpMark + '</strong><br>' |
|||
+ '温度: ' + gpu.temperature + '°C<br>' |
|||
+ '显存: ' + gpu.used_memory + ' / ' + gpu.total_memory + " MB" + '<br>' |
|||
+ '利用率: ' + gpu.utilization + '%'; |
|||
|
|||
// 添加进程信息
|
|||
let processInfo = document.createElement('div'); |
|||
processInfo.classList.add('process-info'); |
|||
processInfo.innerHTML = "<strong>使用情况:</strong>"; |
|||
|
|||
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 += `<span class="process-item" title="${item.cmd}">${item.user} (${item.memory}) </span>`; |
|||
}); |
|||
gpuInfo.appendChild(processInfo); // 将用户信息添加到GPU信息中
|
|||
|
|||
serverCard.appendChild(gpuInfo); |
|||
}); |
|||
// 分割线
|
|||
add_bar(serverCard); |
|||
} |
|||
|
|||
// 单个服务器信息作为child加入
|
|||
serverDataContainer.appendChild(serverCard); |
|||
} |
|||
} |
|||
|
|||
// TODO test
|
|||
fetchData() |
Loading…
Reference in new issue