286 lines
8.3 KiB
Vue
286 lines
8.3 KiB
Vue
<template>
|
|
<div class="main">
|
|
<el-row>
|
|
<re-col :value="24" :xs="24" :sm="24">
|
|
<el-card shadow="never">
|
|
<template #header>
|
|
<div class="flex items-center justify-center">
|
|
<IconifyIconOffline :icon="Monitor" />
|
|
<span class="header-title">基本信息</span>
|
|
</div>
|
|
</template>
|
|
<el-descriptions :column="4" border class="centered-descriptions">
|
|
<el-descriptions-item align="center" label="Redis版本" :span="1">
|
|
{{ cache.info?.redis_version || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="运行模式" :span="1">
|
|
{{ cache.info?.redis_mode === "standalone" ? "单机" : "集群" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="端口" :span="1">
|
|
{{ cache.info?.tcp_port || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="客户端数" :span="1">
|
|
{{ cache.info?.connected_clients || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="运行时间(天)" :span="1">
|
|
{{ cache.info?.uptime_in_days || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="使用内存" :span="1">
|
|
{{ cache.info?.used_memory_human || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="使用CPU" :span="1">
|
|
{{
|
|
cache.info?.used_cpu_user_children !== undefined
|
|
? parseFloat(cache.info.used_cpu_user_children).toFixed(2)
|
|
: "-"
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="内存配置" :span="1">
|
|
{{ cache.info?.maxmemory_human || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="AOF是否开启" :span="1">
|
|
{{ cache.info?.aof_enabled === "0" ? "否" : "是" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="RDB是否成功" :span="1">
|
|
{{ cache.info?.rdb_last_bgsave_status || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="Key数量" :span="1">
|
|
{{ cache.dbSize || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item
|
|
align="center"
|
|
label="网络入口/出口"
|
|
:span="1"
|
|
>
|
|
{{
|
|
cache.info
|
|
? `${cache.info.instantaneous_input_kbps}kps/${cache.info.instantaneous_output_kbps}kps`
|
|
: "-"
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="内存使用率" :span="1">
|
|
{{
|
|
cache.info?.used_memory !== undefined &&
|
|
cache.info?.maxmemory !== undefined &&
|
|
cache.info.maxmemory > 0
|
|
? (
|
|
(cache.info.used_memory / cache.info.maxmemory) *
|
|
100
|
|
).toFixed(2) + "%"
|
|
: "-"
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="操作系统" :span="1">
|
|
{{ cache.info?.os || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="架构位数" :span="1">
|
|
{{ cache.info?.arch_bits || "-" }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item align="center" label="多路复用API" :span="1">
|
|
{{ cache.info?.multiplexing_api || "-" }}
|
|
</el-descriptions-item>
|
|
</el-descriptions>
|
|
</el-card>
|
|
</re-col>
|
|
|
|
<re-col :value="12" :xs="24" :sm="24">
|
|
<el-card shadow="never">
|
|
<template #header>
|
|
<div class="flex items-center justify-center">
|
|
<IconifyIconOffline :icon="PieChart" />
|
|
<span class="header-title">命令统计</span>
|
|
</div>
|
|
</template>
|
|
<div ref="commandstats" style="height: 420px" />
|
|
</el-card>
|
|
</re-col>
|
|
|
|
<re-col :value="12" :xs="24" :sm="24">
|
|
<el-card shadow="never">
|
|
<template #header>
|
|
<div class="flex items-center justify-center">
|
|
<IconifyIconOffline :icon="Odometer" />
|
|
<span class="header-title">内存信息</span>
|
|
</div>
|
|
</template>
|
|
<div ref="usedmemory" style="height: 420px" />
|
|
</el-card>
|
|
</re-col>
|
|
</el-row>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
defineOptions({
|
|
name: "MonitorCache"
|
|
});
|
|
import ReCol from "@/components/ReCol";
|
|
import { ref, onMounted, nextTick, reactive } from "vue";
|
|
import { getCachedMonitorInfoAPI } from "@/api/monitor";
|
|
import * as echarts from "echarts";
|
|
import Monitor from "@iconify-icons/ep/monitor";
|
|
import PieChart from "@iconify-icons/ep/pie-chart";
|
|
import Odometer from "@iconify-icons/ep/odometer";
|
|
import { onBeforeRouteLeave } from "vue-router";
|
|
|
|
const cache = reactive({
|
|
commandStats: [] as { name: string; value: number }[],
|
|
dbSize: 0,
|
|
info: {
|
|
redis_version: "",
|
|
redis_mode: "",
|
|
tcp_port: 0,
|
|
connected_clients: 0,
|
|
uptime_in_days: 0,
|
|
used_memory_human: "",
|
|
used_cpu_user_children: "",
|
|
maxmemory_human: "",
|
|
aof_enabled: "",
|
|
rdb_last_bgsave_status: "",
|
|
instantaneous_input_kbps: 0,
|
|
instantaneous_output_kbps: 0,
|
|
used_memory: 0,
|
|
maxmemory: 0,
|
|
os: "",
|
|
arch_bits: 0,
|
|
multiplexing_api: ""
|
|
}
|
|
});
|
|
|
|
const commandstats = ref(null);
|
|
const usedmemory = ref(null);
|
|
|
|
const getCacheInfo = async () => {
|
|
const res = await getCachedMonitorInfoAPI();
|
|
if (res.success) {
|
|
Object.assign(cache, res.data);
|
|
|
|
nextTick(() => {
|
|
initCommandStatsChart();
|
|
initUsedMemoryChart();
|
|
});
|
|
}
|
|
};
|
|
|
|
const initCommandStatsChart = () => {
|
|
const chart = echarts.init(commandstats.value);
|
|
const commandData = cache.commandStats || [];
|
|
const seriesData = commandData.map((cmd: any) => ({
|
|
name: cmd.name,
|
|
value: parseInt(cmd.value, 10)
|
|
}));
|
|
|
|
const option = {
|
|
title: {
|
|
text: "命令统计",
|
|
left: "center"
|
|
},
|
|
tooltip: {
|
|
trigger: "item",
|
|
formatter: "{a} <br/>{b}: {c} ({d}%)"
|
|
},
|
|
legend: {
|
|
orient: "vertical",
|
|
left: "left"
|
|
},
|
|
series: [
|
|
{
|
|
name: "命令",
|
|
type: "pie",
|
|
radius: "50%",
|
|
data: seriesData,
|
|
emphasis: {
|
|
itemStyle: {
|
|
shadowBlur: 10,
|
|
shadowOffsetX: 0,
|
|
shadowColor: "rgba(0, 0, 0, 0.5)"
|
|
}
|
|
},
|
|
label: {
|
|
show: true,
|
|
formatter: "{b}: {c} ({d}%)"
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
chart.setOption(option);
|
|
};
|
|
|
|
const initUsedMemoryChart = () => {
|
|
const chart = echarts.init(usedmemory.value);
|
|
const usedMemory = cache.info?.used_memory || 0;
|
|
const maxMemory = cache.info?.maxmemory || 0;
|
|
|
|
const option = {
|
|
title: {
|
|
text: "内存信息",
|
|
left: "center"
|
|
},
|
|
tooltip: {
|
|
formatter: "{b} <br/>{a} : " + cache.info.used_memory_human
|
|
},
|
|
series: [
|
|
{
|
|
name: "峰值",
|
|
type: "gauge",
|
|
min: 0,
|
|
max: 1000,
|
|
detail: {
|
|
formatter: cache.info.used_memory_human
|
|
},
|
|
data: [
|
|
{
|
|
value: parseFloat(cache.info.used_memory_human),
|
|
name: "内存消耗"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
};
|
|
|
|
chart.setOption(option);
|
|
};
|
|
/**定时ID */
|
|
const timer = ref();
|
|
onMounted(async () => {
|
|
await getCacheInfo();
|
|
timer.value = setInterval(() => {
|
|
getCacheInfo();
|
|
}, 60000);
|
|
});
|
|
/**页面离开时清除定时器 */
|
|
onBeforeRouteLeave(() => {
|
|
clearInterval(timer.value);
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.icon {
|
|
width: 1em;
|
|
height: 1em;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.header-title {
|
|
margin-left: 0.5em;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.centered-descriptions {
|
|
:deep(.el-descriptions-item__container) {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
:deep(.el-descriptions-item__label) {
|
|
text-align: center;
|
|
}
|
|
|
|
:deep(.el-descriptions-item__content) {
|
|
text-align: center;
|
|
}
|
|
}
|
|
</style>
|