iceshrimp/packages/client/src/widgets/server-metric/cpu-mem.vue
2023-04-07 17:01:42 -07:00

194 lines
4.5 KiB
Vue

<template>
<div class="lcfyofjk">
<svg :viewBox="`0 0 ${viewBoxX} ${viewBoxY}`">
<defs>
<linearGradient :id="cpuGradientId" x1="0" x2="0" y1="1" y2="0">
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
</linearGradient>
<mask
:id="cpuMaskId"
x="0"
y="0"
:width="viewBoxX"
:height="viewBoxY"
>
<polygon
:points="cpuPolygonPoints"
fill="#fff"
fill-opacity="0.5"
/>
<polyline
:points="cpuPolylinePoints"
fill="none"
stroke="#fff"
stroke-width="1"
/>
<circle :cx="cpuHeadX" :cy="cpuHeadY" r="1.5" fill="#fff" />
</mask>
</defs>
<rect
x="-2"
y="-2"
:width="viewBoxX + 4"
:height="viewBoxY + 4"
:style="`stroke: none; fill: url(#${cpuGradientId}); mask: url(#${cpuMaskId})`"
/>
<text x="1" y="5">
CPU
<tspan>{{ cpuP }}%</tspan>
</text>
</svg>
<svg :viewBox="`0 0 ${viewBoxX} ${viewBoxY}`">
<defs>
<linearGradient :id="memGradientId" x1="0" x2="0" y1="1" y2="0">
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
</linearGradient>
<mask
:id="memMaskId"
x="0"
y="0"
:width="viewBoxX"
:height="viewBoxY"
>
<polygon
:points="memPolygonPoints"
fill="#fff"
fill-opacity="0.5"
/>
<polyline
:points="memPolylinePoints"
fill="none"
stroke="#fff"
stroke-width="1"
/>
<circle :cx="memHeadX" :cy="memHeadY" r="1.5" fill="#fff" />
</mask>
</defs>
<rect
x="-2"
y="-2"
:width="viewBoxX + 4"
:height="viewBoxY + 4"
:style="`stroke: none; fill: url(#${memGradientId}); mask: url(#${memMaskId})`"
/>
<text x="1" y="5">
MEM
<tspan>{{ memP }}%</tspan>
</text>
</svg>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onBeforeUnmount } from "vue";
import { v4 as uuid } from "uuid";
const props = defineProps<{
connection: any;
meta: any;
}>();
let viewBoxX: number = $ref(50);
let viewBoxY: number = $ref(30);
let stats: any[] = $ref([]);
const cpuGradientId = uuid();
const cpuMaskId = uuid();
const memGradientId = uuid();
const memMaskId = uuid();
let cpuPolylinePoints: string = $ref("");
let memPolylinePoints: string = $ref("");
let cpuPolygonPoints: string = $ref("");
let memPolygonPoints: string = $ref("");
let cpuHeadX: any = $ref(null);
let cpuHeadY: any = $ref(null);
let memHeadX: any = $ref(null);
let memHeadY: any = $ref(null);
let cpuP: string = $ref("");
let memP: string = $ref("");
onMounted(() => {
props.connection.on("stats", onStats);
props.connection.on("statsLog", onStatsLog);
props.connection.send("requestLog", {
id: Math.random().toString().substr(2, 8),
});
});
onBeforeUnmount(() => {
props.connection.off("stats", onStats);
props.connection.off("statsLog", onStatsLog);
});
function onStats(connStats) {
stats.push(connStats);
if (stats.length > 50) stats.shift();
let cpuPolylinePointsStats = stats.map((s, i) => [
viewBoxX - (stats.length - 1 - i),
(1 - s.cpu) * viewBoxY,
]);
let memPolylinePointsStats = stats.map((s, i) => [
viewBoxX - (stats.length - 1 - i),
(1 - s.mem.active / props.meta.mem.total) * viewBoxY,
]);
cpuPolylinePoints = cpuPolylinePointsStats
.map((xy) => `${xy[0]},${xy[1]}`)
.join(" ");
memPolylinePoints = memPolylinePointsStats
.map((xy) => `${xy[0]},${xy[1]}`)
.join(" ");
cpuPolygonPoints = `${
viewBoxX - (stats.length - 1)
},${viewBoxY} ${cpuPolylinePoints} ${viewBoxX},${viewBoxY}`;
memPolygonPoints = `${
viewBoxX - (stats.length - 1)
},${viewBoxY} ${memPolylinePoints} ${viewBoxX},${viewBoxY}`;
cpuHeadX = cpuPolylinePointsStats[cpuPolylinePointsStats.length - 1][0];
cpuHeadY = cpuPolylinePointsStats[cpuPolylinePointsStats.length - 1][1];
memHeadX = memPolylinePointsStats[memPolylinePointsStats.length - 1][0];
memHeadY = memPolylinePointsStats[memPolylinePointsStats.length - 1][1];
cpuP = (connStats.cpu * 100).toFixed(0);
memP = ((connStats.mem.active / props.meta.mem.total) * 100).toFixed(0);
}
function onStatsLog(statsLog) {
for (const revStats of [...statsLog].reverse()) {
onStats(revStats);
}
}
</script>
<style lang="scss" scoped>
.lcfyofjk {
display: flex;
> svg {
display: block;
padding: 10px;
width: 50%;
&:first-child {
padding-right: 5px;
}
&:last-child {
padding-left: 5px;
}
> text {
font-size: 5px;
fill: currentColor;
> tspan {
opacity: 0.5;
}
}
}
}
</style>