mirror of
https://github.com/donaldzou/WGDashboard
synced 2025-02-26 05:58:47 +00:00
Refactored system status into a class. Added charts
This commit is contained in:
parent
84069ee882
commit
e603af5f24
133
src/dashboard.py
133
src/dashboard.py
@ -2948,74 +2948,77 @@ def API_Email_PreviewBody():
|
||||
except Exception as e:
|
||||
return ResponseObject(False, message=str(e))
|
||||
|
||||
|
||||
from modules.SystemStatus import SystemStatus
|
||||
SystemStatus = SystemStatus()
|
||||
|
||||
@app.get(f'{APP_PREFIX}/api/systemStatus')
|
||||
def API_SystemStatus():
|
||||
cpu_percpu = psutil.cpu_percent(interval=0.5, percpu=True)
|
||||
cpu = psutil.cpu_percent(interval=0.5)
|
||||
memory = psutil.virtual_memory()
|
||||
swap_memory = psutil.swap_memory()
|
||||
disks = psutil.disk_partitions()
|
||||
network = psutil.net_io_counters(pernic=True, nowrap=True)
|
||||
|
||||
status = {
|
||||
"cpu": {
|
||||
"cpu_percent": cpu,
|
||||
"cpu_percent_per_cpu": cpu_percpu,
|
||||
},
|
||||
"memory": {
|
||||
"virtual_memory": {
|
||||
"total": memory.total,
|
||||
"available": memory.available,
|
||||
"percent": memory.percent
|
||||
},
|
||||
"swap_memory": {
|
||||
"total": swap_memory.total,
|
||||
"used": swap_memory.used,
|
||||
"percent": swap_memory.percent
|
||||
}
|
||||
},
|
||||
"disk": {},
|
||||
"network": {},
|
||||
"process": {
|
||||
"cpu_top_10": [],
|
||||
"memory_top_10": []
|
||||
}
|
||||
}
|
||||
for d in disks:
|
||||
detail = psutil.disk_usage(d.mountpoint)
|
||||
status['disk'][d.mountpoint] = {
|
||||
"total": detail.total,
|
||||
"used": detail.used,
|
||||
"free": detail.free,
|
||||
"percent": detail.percent
|
||||
}
|
||||
for i in network.keys():
|
||||
status["network"][i] = {
|
||||
"byte_sent": network[i].bytes_sent,
|
||||
"byte_recv": network[i].bytes_recv
|
||||
}
|
||||
|
||||
while True:
|
||||
try:
|
||||
processes = list(psutil.process_iter())
|
||||
status["process"]["cpu_top_10"] = sorted(list(map(lambda x : {
|
||||
"name": x.name(),
|
||||
"command": " ".join(x.cmdline()),
|
||||
"pid": x.pid,
|
||||
"cpu_percent": x.cpu_percent()
|
||||
}, processes)), key=lambda x : x['cpu_percent'], reverse=True)[:10]
|
||||
status["process"]["memory_top_10"] = sorted(list(map(lambda x : {
|
||||
"name": x.name(),
|
||||
"command": " ".join(x.cmdline()),
|
||||
"pid": x.pid,
|
||||
"memory_percent": x.memory_percent()
|
||||
}, processes)), key=lambda x : x['memory_percent'], reverse=True)[:10]
|
||||
break
|
||||
except Exception as e:
|
||||
continue
|
||||
return ResponseObject(data=status)
|
||||
# cpu_percpu = psutil.cpu_percent(interval=0.5, percpu=True)
|
||||
# cpu = psutil.cpu_percent(interval=0.5)
|
||||
# memory = psutil.virtual_memory()
|
||||
# swap_memory = psutil.swap_memory()
|
||||
# disks = psutil.disk_partitions()
|
||||
# network = psutil.net_io_counters(pernic=True, nowrap=True)
|
||||
#
|
||||
#
|
||||
# status = {
|
||||
# "cpu": {
|
||||
# "cpu_percent": cpu,
|
||||
# "cpu_percent_per_cpu": cpu_percpu,
|
||||
# },
|
||||
# "memory": {
|
||||
# "virtual_memory": {
|
||||
# "total": memory.total,
|
||||
# "available": memory.available,
|
||||
# "percent": memory.percent
|
||||
# },
|
||||
# "swap_memory": {
|
||||
# "total": swap_memory.total,
|
||||
# "used": swap_memory.used,
|
||||
# "percent": swap_memory.percent
|
||||
# }
|
||||
# },
|
||||
# "disk": {},
|
||||
# "network": {},
|
||||
# "process": {
|
||||
# "cpu_top_10": [],
|
||||
# "memory_top_10": []
|
||||
# },
|
||||
# "SystemStatus": systemStatus
|
||||
# }
|
||||
# for d in disks:
|
||||
# detail = psutil.disk_usage(d.mountpoint)
|
||||
# status['disk'][d.mountpoint] = {
|
||||
# "total": detail.total,
|
||||
# "used": detail.used,
|
||||
# "free": detail.free,
|
||||
# "percent": detail.percent
|
||||
# }
|
||||
# for i in network.keys():
|
||||
# status["network"][i] = {
|
||||
# "byte_sent": network[i].bytes_sent,
|
||||
# "byte_recv": network[i].bytes_recv
|
||||
# }
|
||||
#
|
||||
# while True:
|
||||
# try:
|
||||
# processes = list(psutil.process_iter())
|
||||
# status["process"]["cpu_top_10"] = sorted(list(map(lambda x : {
|
||||
# "name": x.name(),
|
||||
# "command": " ".join(x.cmdline()),
|
||||
# "pid": x.pid,
|
||||
# "cpu_percent": x.cpu_percent()
|
||||
# }, processes)), key=lambda x : x['cpu_percent'], reverse=True)[:10]
|
||||
# status["process"]["memory_top_10"] = sorted(list(map(lambda x : {
|
||||
# "name": x.name(),
|
||||
# "command": " ".join(x.cmdline()),
|
||||
# "pid": x.pid,
|
||||
# "memory_percent": x.memory_percent()
|
||||
# }, processes)), key=lambda x : x['memory_percent'], reverse=True)[:10]
|
||||
# break
|
||||
# except Exception as e:
|
||||
# continue
|
||||
return ResponseObject(data=SystemStatus)
|
||||
|
||||
@app.get(f'{APP_PREFIX}/api/protocolsEnabled')
|
||||
def API_ProtocolsEnabled():
|
||||
|
@ -3,7 +3,25 @@ from asyncio.subprocess import Process
|
||||
import psutil
|
||||
|
||||
class SystemStatus:
|
||||
pass
|
||||
def __init__(self):
|
||||
self.CPU = CPU()
|
||||
self.MemoryVirtual = Memory('virtual')
|
||||
self.MemorySwap = Memory('swap')
|
||||
self.Disks = Disks()
|
||||
self.NetworkInterfaces = NetworkInterfaces()
|
||||
self.Processes = Processes()
|
||||
def toJson(self):
|
||||
return {
|
||||
"CPU": self.CPU,
|
||||
"Memory": {
|
||||
"VirtualMemory": self.MemoryVirtual,
|
||||
"SwapMemory": self.MemorySwap
|
||||
},
|
||||
"Disks": self.Disks,
|
||||
"NetworkInterfaces": self.NetworkInterfaces,
|
||||
"Processes": self.Processes
|
||||
}
|
||||
|
||||
|
||||
class CPU:
|
||||
def __init__(self):
|
||||
@ -11,8 +29,8 @@ class CPU:
|
||||
self.cpu_percent_per_cpu: list[float] = []
|
||||
def getData(self):
|
||||
try:
|
||||
self.cpu_percent = psutil.cpu_percent(interval=0.5, percpu=True)
|
||||
self.cpu_percent_per_cpu = psutil.cpu_percent(interval=0.5)
|
||||
self.cpu_percent_per_cpu = psutil.cpu_percent(interval=0.5, percpu=True)
|
||||
self.cpu_percent = psutil.cpu_percent(interval=0.5)
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
@ -21,22 +39,37 @@ class CPU:
|
||||
|
||||
class Memory:
|
||||
def __init__(self, memoryType: str):
|
||||
self.__memoryType = memoryType
|
||||
self.__memoryType__ = memoryType
|
||||
self.total = 0
|
||||
self.available = 0
|
||||
self.percent = 0
|
||||
def getData(self):
|
||||
if self.__memoryType == "virtual":
|
||||
try:
|
||||
if self.__memoryType__ == "virtual":
|
||||
memory = psutil.virtual_memory()
|
||||
else:
|
||||
memory = psutil.swap_memory()
|
||||
self.total = memory.total
|
||||
self.available = memory.available
|
||||
self.percent = memory.percent
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.__dict__
|
||||
|
||||
class Disks:
|
||||
def __init__(self):
|
||||
self.disks : list[Disk] = []
|
||||
def getData(self):
|
||||
try:
|
||||
self.disks = list(map(lambda x : Disk(x.mountpoint), psutil.disk_partitions()))
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.disks
|
||||
|
||||
class Disk:
|
||||
def __init__(self, mountPoint: str):
|
||||
self.total = 0
|
||||
@ -45,11 +78,14 @@ class Disk:
|
||||
self.percent = 0
|
||||
self.mountPoint = mountPoint
|
||||
def getData(self):
|
||||
try:
|
||||
disk = psutil.disk_usage(self.mountPoint)
|
||||
self.total = disk.total
|
||||
self.free = disk.free
|
||||
self.used = disk.used
|
||||
self.percent = disk.percent
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.__dict__
|
||||
@ -58,9 +94,12 @@ class NetworkInterfaces:
|
||||
def __init__(self):
|
||||
self.interfaces = {}
|
||||
def getData(self):
|
||||
try:
|
||||
network = psutil.net_io_counters(pernic=True, nowrap=True)
|
||||
for i in network.keys():
|
||||
self.interfaces[i] = network[i]._asdict()
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.interfaces
|
||||
@ -78,19 +117,21 @@ class Processes:
|
||||
self.CPU_Top_10_Processes: list[Processes.Process] = []
|
||||
self.Memory_Top_10_Processes: list[Processes.Process] = []
|
||||
def getData(self):
|
||||
while True:
|
||||
try:
|
||||
processes = list(psutil.process_iter())
|
||||
self.CPU_Top_10_Processes = sorted(list(map(lambda x :
|
||||
Processes.Process(x.name(), " ".join(x.cmdline()), x.pid, x.cpu_percent()), processes)),
|
||||
key=lambda x : x.percent, reverse=True)[:10]
|
||||
self.Memory_Top_10_Processes = sorted(list(map(lambda x :
|
||||
Processes.Process(x.name(), " ".join(x.cmdline()), x.pid, x.memory_percent()), processes)),
|
||||
key=lambda x : x.percent, reverse=True)[:10]
|
||||
self.CPU_Top_10_Processes = sorted(
|
||||
list(map(lambda x : Processes.Process(x.name(), " ".join(x.cmdline()), x.pid, x.cpu_percent()), processes)),
|
||||
key=lambda x : x.percent, reverse=True)[:20]
|
||||
self.Memory_Top_10_Processes = sorted(
|
||||
list(map(lambda x : Processes.Process(x.name(), " ".join(x.cmdline()), x.pid, x.memory_percent()), processes)),
|
||||
key=lambda x : x.percent, reverse=True)[:20]
|
||||
break
|
||||
except Exception as e:
|
||||
continue
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return {
|
||||
"cpu_top_10": self.CPU_Top_10_Processes,
|
||||
"memory_top_10": self.Memory_Top_10_Processes
|
||||
}
|
||||
|
||||
p = Processes()
|
||||
print(p.toJson())
|
@ -10,7 +10,7 @@ const props = defineProps(["process", "cpu"])
|
||||
<samp>{{process.command ? process.command : process.name}}</samp>
|
||||
</small>
|
||||
<small class="ms-auto">
|
||||
{{cpu ? process.cpu_percent : (Math.round((process.memory_percent + Number.EPSILON) * 10) / 10)}}%
|
||||
{{(Math.round((process.percent + Number.EPSILON) * 10) / 10)}}%
|
||||
</small>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -2,8 +2,7 @@
|
||||
import {computed, ref} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
mount: String,
|
||||
percentage: Number,
|
||||
mount: Object,
|
||||
align: Boolean,
|
||||
square: Boolean
|
||||
})
|
||||
@ -19,7 +18,7 @@ const squareHeight = computed(() => {
|
||||
<div class="flex-grow-1 square rounded-3 border position-relative"
|
||||
@mouseenter="show = true"
|
||||
@mouseleave="show = false"
|
||||
:style="{'background-color': `rgb(25 135 84 / ${percentage}%)`}">
|
||||
:style="{'background-color': `rgb(25 135 84 / ${mount.percent}%)`}">
|
||||
<Transition name="zoomReversed">
|
||||
<div
|
||||
v-if="show"
|
||||
@ -29,10 +28,10 @@ const squareHeight = computed(() => {
|
||||
:class="[align ? 'end-0':'start-0']"
|
||||
>
|
||||
<small class="text-muted me-2">
|
||||
<samp>{{mount}}</samp>
|
||||
<samp>{{mount.mountPoint}}</samp>
|
||||
</small>
|
||||
<small class="fw-bold">
|
||||
{{percentage}}%
|
||||
{{mount.percent}}%
|
||||
</small>
|
||||
</div>
|
||||
</Transition>
|
||||
|
@ -7,8 +7,6 @@ import StorageMount from "@/components/systemStatusComponents/storageMount.vue";
|
||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||
|
||||
const dashboardStore = DashboardConfigurationStore()
|
||||
|
||||
// const data = ref(undefined)
|
||||
let interval = null;
|
||||
|
||||
onMounted(() => {
|
||||
@ -43,19 +41,19 @@ const data = computed(() => {
|
||||
</h6>
|
||||
<h6 class="ms-auto">
|
||||
<span v-if="data">
|
||||
{{ data.cpu.cpu_percent }}%
|
||||
{{ data.CPU.cpu_percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border spinner-border-sm"></span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 6px">
|
||||
<div class="progress-bar" :style="{width: `${data?.cpu.cpu_percent}%` }"></div>
|
||||
<div class="progress-bar" :style="{width: `${data?.CPU.cpu_percent}%` }"></div>
|
||||
</div>
|
||||
<div class="d-flex mt-2 gap-1">
|
||||
<CpuCore
|
||||
v-for="(cpu, count) in data?.cpu.cpu_percent_per_cpu"
|
||||
v-for="(cpu, count) in data?.CPU.cpu_percent_per_cpu"
|
||||
:key="count"
|
||||
:align="(count + 1) > Math.round(data?.cpu.cpu_percent_per_cpu.length / 2)"
|
||||
:align="(count + 1) > Math.round(data?.CPU.cpu_percent_per_cpu.length / 2)"
|
||||
:core_number="count" :percentage="cpu"
|
||||
></CpuCore>
|
||||
</div>
|
||||
@ -68,20 +66,20 @@ const data = computed(() => {
|
||||
</h6>
|
||||
<h6 class="ms-auto">
|
||||
<span v-if="data">
|
||||
{{ data?.disk['/'].percent }}%
|
||||
{{ data?.Disks.find(x => x.mountPoint === '/').percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border spinner-border-sm"></span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 6px">
|
||||
<div class="progress-bar bg-success" :style="{width: `${data?.disk['/'].percent}%` }"></div>
|
||||
<div class="progress-bar bg-success" :style="{width: `${data?.Disks.find(x => x.mountPoint === '/').percent}%` }"></div>
|
||||
</div>
|
||||
<div class="d-flex mt-2 gap-1">
|
||||
<StorageMount v-for="(disk, count) in Object.keys(data?.disk)"
|
||||
<StorageMount v-for="(disk, count) in data?.Disks"
|
||||
v-if="data"
|
||||
:key="count"
|
||||
:align="(count + 1) > Math.round(Object.keys(data?.disk).length / 2)"
|
||||
:mount="disk" :percentage="data?.disk[disk].percent"
|
||||
:key="disk.mountPoint"
|
||||
:align="(count + 1) > Math.round(data?.Disks.length / 2)"
|
||||
:mount="disk"
|
||||
></StorageMount>
|
||||
</div>
|
||||
</div>
|
||||
@ -93,13 +91,13 @@ const data = computed(() => {
|
||||
</h6>
|
||||
<h6 class="ms-auto">
|
||||
<span v-if="data">
|
||||
{{ data?.memory.virtual_memory.percent }}%
|
||||
{{ data?.Memory.VirtualMemory.percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border spinner-border-sm"></span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 6px">
|
||||
<div class="progress-bar bg-info" :style="{width: `${data?.memory.virtual_memory.percent}%` }"></div>
|
||||
<div class="progress-bar bg-info" :style="{width: `${data?.Memory.VirtualMemory.percent}%` }"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-12 col-xl-3">
|
||||
@ -110,13 +108,13 @@ const data = computed(() => {
|
||||
</h6>
|
||||
<h6 class="ms-auto">
|
||||
<span v-if="data">
|
||||
{{ data?.memory.swap_memory.percent }}%
|
||||
{{ data?.Memory.SwapMemory.percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border spinner-border-sm"></span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 6px">
|
||||
<div class="progress-bar bg-warning" :style="{width: `${data?.memory.swap_memory.percent}%` }"></div>
|
||||
<div class="progress-bar bg-warning" :style="{width: `$ data?.Memory.SwapMemory.percent}%` }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,6 +12,36 @@ const data = computed(() => {
|
||||
return dashboardStore.SystemStatus
|
||||
})
|
||||
let interval = null;
|
||||
import {
|
||||
Chart,
|
||||
LineElement,
|
||||
BarElement,
|
||||
BarController,
|
||||
LineController,
|
||||
LinearScale,
|
||||
Legend,
|
||||
Title,
|
||||
Tooltip,
|
||||
CategoryScale,
|
||||
PointElement,
|
||||
Filler
|
||||
} from 'chart.js';
|
||||
import {Line} from "vue-chartjs";
|
||||
import dayjs from "dayjs";
|
||||
import {GetLocale} from "@/utilities/locale.js";
|
||||
Chart.register(
|
||||
LineElement,
|
||||
BarElement,
|
||||
BarController,
|
||||
LineController,
|
||||
LinearScale,
|
||||
Legend,
|
||||
Title,
|
||||
Tooltip,
|
||||
CategoryScale,
|
||||
PointElement,
|
||||
Filler
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getData()
|
||||
@ -24,11 +54,97 @@ onBeforeUnmount(() => {
|
||||
clearInterval(interval)
|
||||
})
|
||||
|
||||
const historicalChartTimestamp = ref([])
|
||||
const historicalCpuUsage = ref([])
|
||||
const historicalVirtualMemoryUsage = ref([])
|
||||
const historicalSwapMemoryUsage = ref([])
|
||||
let i = 0.1
|
||||
const getData = () => {
|
||||
fetchGet("/api/systemStatus", {}, (res) => {
|
||||
historicalChartTimestamp.value.push(dayjs().format("HH:mm:ss A"))
|
||||
dashboardStore.SystemStatus = res.data
|
||||
historicalCpuUsage.value.push(res.data.CPU.cpu_percent)
|
||||
historicalVirtualMemoryUsage.value.push(res.data.Memory.VirtualMemory.percent)
|
||||
historicalSwapMemoryUsage.value.push(res.data.Memory.SwapMemory.percent)
|
||||
})
|
||||
}
|
||||
|
||||
const chartOption = computed(() => {
|
||||
return {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: true
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: (tooltipItem) => {
|
||||
return `${tooltipItem.formattedValue}%`
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
grid: {
|
||||
display: false
|
||||
},
|
||||
},
|
||||
y:{
|
||||
ticks: {
|
||||
callback: (val, index) => {
|
||||
return `${val}%`
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
display: false
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const cpuHistoricalChartData = computed(() => {
|
||||
return {
|
||||
labels: [...historicalChartTimestamp.value],
|
||||
datasets: [
|
||||
{
|
||||
label: GetLocale('CPU Usage'),
|
||||
data: [...historicalCpuUsage.value],
|
||||
fill: 'start',
|
||||
backgroundColor: '#0d6efd50',
|
||||
borderColor: '#0d6efd',
|
||||
tension: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const memoryHistoricalChartData = computed(() => {
|
||||
return {
|
||||
labels: [...historicalChartTimestamp.value],
|
||||
datasets: [
|
||||
{
|
||||
label: GetLocale('Memory Usage'),
|
||||
data: [...historicalVirtualMemoryUsage.value],
|
||||
fill: 1,
|
||||
borderColor: '#0dcaf0',
|
||||
backgroundColor: '#0dcaf050',
|
||||
tension: 0
|
||||
},
|
||||
{
|
||||
label: GetLocale('Swap Memory Usage'),
|
||||
data: [...historicalSwapMemoryUsage.value],
|
||||
fill: 'start',
|
||||
backgroundColor: '#ffc10750',
|
||||
borderColor: '#ffc107',
|
||||
tension: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -36,8 +152,8 @@ const getData = () => {
|
||||
<div class="col-sm-6">
|
||||
<div class="card rounded-3 h-100 shadow">
|
||||
<div class="card-body p-4">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 d-flex flex-column gap-3">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<div class="d-flex flex-column gap-3" style="height: 130px">
|
||||
<div class="d-flex align-items-center">
|
||||
<h3 class="text-muted mb-0">
|
||||
<i class="bi bi-cpu-fill me-2"></i>
|
||||
@ -45,42 +161,58 @@ const getData = () => {
|
||||
</h3>
|
||||
<h3 class="ms-auto mb-0">
|
||||
<span v-if="data">
|
||||
{{ data.cpu.cpu_percent }}%
|
||||
{{ data.CPU.cpu_percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 10px">
|
||||
<div class="progress-bar" :style="{width: `${data?.cpu.cpu_percent}%` }"></div>
|
||||
<div class="progress-bar" :style="{width: `${data?.CPU.cpu_percent}%` }"></div>
|
||||
</div>
|
||||
<div class="d-flex gap-1">
|
||||
<CpuCore
|
||||
v-for="(cpu, count) in data?.cpu.cpu_percent_per_cpu"
|
||||
v-for="(cpu, count) in data?.CPU.cpu_percent_per_cpu"
|
||||
:square="true"
|
||||
:key="count"
|
||||
:align="(count + 1) > Math.round(data?.cpu.cpu_percent_per_cpu.length / 2)"
|
||||
:align="(count + 1) > Math.round(data?.CPU.cpu_percent_per_cpu.length / 2)"
|
||||
:core_number="count" :percentage="cpu"
|
||||
></CpuCore>
|
||||
</div>
|
||||
<h5 class="mb-0">Processes</h5>
|
||||
</div>
|
||||
<Line
|
||||
:options="chartOption"
|
||||
:data="cpuHistoricalChartData"
|
||||
style="width: 100%; height: 200px; max-height: 200px"
|
||||
></Line>
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mb-0">
|
||||
<LocaleText t="Processes"></LocaleText>
|
||||
</h5>
|
||||
<h6 class="mb-0 ms-auto text-muted">
|
||||
<small>
|
||||
<LocaleText t="CPU Usage"></LocaleText>
|
||||
</small>
|
||||
</h6>
|
||||
|
||||
</div>
|
||||
<hr class="my-1">
|
||||
<div class="position-relative">
|
||||
<TransitionGroup name="process">
|
||||
<Process
|
||||
:key="p.pid"
|
||||
:cpu="true"
|
||||
:process="p" v-for="p in data?.process.cpu_top_10"></Process>
|
||||
:process="p" v-for="p in data?.Processes.cpu_top_10"></Process>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="card rounded-3 h-100 shadow">
|
||||
<div class="card-body p-4">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 d-flex flex-column gap-3">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<div class="d-flex flex-column gap-3" style="height: 130px">
|
||||
<div class="d-flex align-items-center">
|
||||
<h3 class="text-muted">
|
||||
<i class="bi bi-memory me-2"></i>
|
||||
@ -88,27 +220,44 @@ const getData = () => {
|
||||
</h3>
|
||||
<h3 class="ms-auto">
|
||||
<span v-if="data">
|
||||
{{ data.memory.virtual_memory.percent }}%
|
||||
{{ data?.Memory.VirtualMemory.percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 10px">
|
||||
<div class="progress-bar bg-info" :style="{width: `${data?.memory.virtual_memory.percent}%` }"></div>
|
||||
<div class="progress-bar bg-info" :style="{width: `${data?.Memory.VirtualMemory.percent}%` }"></div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<h6 class="mb-0">Swap Memory</h6>
|
||||
<h6 class="mb-0 ms-auto">{{data?.memory.swap_memory.percent}}%</h6>
|
||||
<h6 class="mb-0 ms-auto">{{data?.Memory.SwapMemory.percent}}%</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 10px">
|
||||
<div class="progress-bar bg-info-subtle" :style="{width: `${data?.memory.swap_memory.percent}%` }"></div>
|
||||
<div class="progress-bar bg-info-subtle" :style="{width: `${data?.Memory.SwapMemory.percent}%` }"></div>
|
||||
</div>
|
||||
<h5 class="mb-0">Processes</h5>
|
||||
</div>
|
||||
<Line
|
||||
:options="chartOption"
|
||||
:data="memoryHistoricalChartData"
|
||||
style="width: 100%; height: 200px; max-height: 200px"
|
||||
></Line>
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mb-0">
|
||||
<LocaleText t="Processes"></LocaleText>
|
||||
</h5>
|
||||
<h6 class="mb-0 ms-auto text-muted">
|
||||
<small>
|
||||
<LocaleText t="Memory Usage"></LocaleText>
|
||||
</small>
|
||||
</h6>
|
||||
|
||||
</div>
|
||||
<hr class="my-1">
|
||||
<div class="position-relative">
|
||||
<TransitionGroup name="process">
|
||||
<Process
|
||||
:key="p.pid"
|
||||
:process="p" v-for="p in data?.process.memory_top_10">
|
||||
:process="p" v-for="p in data?.Processes.memory_top_10">
|
||||
</Process>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
@ -116,7 +265,6 @@ const getData = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<div class="card rounded-3 h-100 shadow">
|
||||
<div class="card-body p-4 d-flex gap-3 flex-column">
|
||||
@ -127,13 +275,13 @@ const getData = () => {
|
||||
</h3>
|
||||
<h3 class="ms-auto mb-0">
|
||||
<span v-if="data">
|
||||
<LocaleText :t="Object.keys(data.network).length + ' Interface' + (Object.keys(data.network).length > 1 ? 's':'')"></LocaleText>
|
||||
<LocaleText :t="Object.keys(data.NetworkInterfaces).length + ' Interface' + (Object.keys(data.NetworkInterfaces).length > 1 ? 's':'')"></LocaleText>
|
||||
</span>
|
||||
<span v-else class="spinner-border"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div v-if="data" class="row g-3">
|
||||
<div v-for="(key, index) in Object.keys(data.network).sort()"
|
||||
<div v-for="(key, index) in Object.keys(data.NetworkInterfaces).sort()"
|
||||
class="col-sm-6 fadeIn">
|
||||
<div class="d-flex mb-2">
|
||||
<h6 class="mb-0">
|
||||
@ -142,22 +290,22 @@ const getData = () => {
|
||||
<h6 class="mb-0 ms-auto d-flex gap-2">
|
||||
<span class="text-info">
|
||||
<i class="bi bi-arrow-down"></i>
|
||||
{{ Math.round((data.network[key].byte_recv / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
|
||||
{{ Math.round((data.NetworkInterfaces[key].bytes_recv / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
|
||||
</span>
|
||||
<span class="text-warning">
|
||||
<i class="bi bi-arrow-up"></i>
|
||||
{{ Math.round((data.network[key].byte_sent / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
|
||||
{{ Math.round((data.NetworkInterfaces[key].bytes_sent / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
|
||||
</span>
|
||||
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 10px">
|
||||
<div class="progress-bar bg-info"
|
||||
v-if="data.network[key].byte_recv > 0"
|
||||
:style="{width: `${(data.network[key].byte_recv / (data.network[key].byte_sent + data.network[key].byte_recv)) * 100}%` }"></div>
|
||||
v-if="data.NetworkInterfaces[key].byte_recv > 0"
|
||||
:style="{width: `${(data.NetworkInterfaces[key].bytes_recv / (data.NetworkInterfaces[key].byte_sent + data.NetworkInterfaces[key].byte_recv)) * 100}%` }"></div>
|
||||
<div class="progress-bar bg-warning"
|
||||
v-if="data.network[key].byte_sent > 0"
|
||||
:style="{width: `${(data.network[key].byte_sent / (data.network[key].byte_sent + data.network[key].byte_recv)) * 100}%` }"></div>
|
||||
v-if="data.NetworkInterfaces[key].byte_sent > 0"
|
||||
:style="{width: `${(data.NetworkInterfaces[key].bytes_sent / (data.NetworkInterfaces[key].byte_sent + data.NetworkInterfaces[key].byte_recv)) * 100}%` }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -174,28 +322,28 @@ const getData = () => {
|
||||
</h3>
|
||||
<h3 class="ms-auto mb-0">
|
||||
<span v-if="data">
|
||||
<LocaleText :t="Object.keys(data.disk).length + ' Partition' + (Object.keys(data.disk).length > 1 ? 's':'')"></LocaleText>
|
||||
<LocaleText :t="data.Disks.length + ' Partition' + (data.Disks.length > 1 ? 's':'')"></LocaleText>
|
||||
</span>
|
||||
<span v-else class="spinner-border"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div v-for="(key, index) in Object.keys(data.disk).sort()" class="col-sm-6 fadeIn"
|
||||
<div v-for="disk in data.Disks" class="col-sm-6 fadeIn"
|
||||
v-if="data">
|
||||
<div class="d-flex mb-2">
|
||||
<h6 class="mb-0">
|
||||
<samp>{{key}}</samp>
|
||||
<samp>{{disk.mountPoint}}</samp>
|
||||
</h6>
|
||||
<h6 class="mb-0 ms-auto d-flex gap-2">
|
||||
<span class="text-success">
|
||||
{{ Math.round((data.disk[key].used / 1024000000 + Number.EPSILON) * 100) / 100}} / {{ Math.round((data.disk[key].total / 1024000000 + Number.EPSILON) * 100) / 100}} GB Used
|
||||
{{ Math.round((disk.used / 1024000000 + Number.EPSILON) * 100) / 100}} / {{ Math.round((disk.total / 1024000000 + Number.EPSILON) * 100) / 100}} GB Used
|
||||
</span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 20px">
|
||||
<div class="progress-bar bg-success"
|
||||
:style="{width: `${data.disk[key].percent}%`}">
|
||||
{{ data.disk[key].percent }}%
|
||||
:style="{width: `${disk.percent}%`}">
|
||||
{{ disk.percent }}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -217,7 +365,7 @@ const getData = () => {
|
||||
.process-enter-from,
|
||||
.process-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.process-leave-active {
|
||||
|
Loading…
Reference in New Issue
Block a user