Redis监控图标使用Echart组件整合

(cherry picked from commit bf629a9554)
This commit is contained in:
Chika 2023-05-12 15:30:01 +08:00 committed by shizhong
parent 7a5993c584
commit 80f1c08951
2 changed files with 216 additions and 195 deletions

View File

@ -342,6 +342,28 @@ const remainingRouter: AppRouteRecordRaw[] = [
} }
] ]
}, },
{
path: '/infra',
component: Layout,
name: 'InfraRedis',
meta: {
hidden: true
},
children: [
{
path: '/infra/redis',
component: () => import('@/views/infra/redis/index.vue'),
name: 'InfraRedis',
meta: {
noCache: true,
hidden: true,
canTo: true,
title: 'REDIS测试测试测试',
activeMenu: 'infra/redis/index'
}
}
]
},
{ {
path: '/property', path: '/property',
component: Layout, component: Layout,

View File

@ -1,6 +1,9 @@
<template> <template>
<doc-alert title="Redis 缓存" url="https://doc.iocoder.cn/redis-cache/" />
<doc-alert title="本地缓存" url="https://doc.iocoder.cn/local-cache/" />
<el-scrollbar height="calc(100vh - 88px - 40px - 50px)"> <el-scrollbar height="calc(100vh - 88px - 40px - 50px)">
<el-row> <el-row>
<!-- 基本信息 -->
<el-col :span="24" class="card-box" shadow="hover"> <el-col :span="24" class="card-box" shadow="hover">
<el-card> <el-card>
<el-descriptions title="基本信息" :column="6" border> <el-descriptions title="基本信息" :column="6" border>
@ -44,229 +47,225 @@
</el-descriptions> </el-descriptions>
</el-card> </el-card>
</el-col> </el-col>
<!-- 命令统计 -->
<el-col :span="12" class="mt-3"> <el-col :span="12" class="mt-3">
<el-card :gutter="12" shadow="hover"> <el-card :gutter="12" shadow="hover">
<div ref="commandStatsRef" class="h-88"></div> <Echart :options="commandStatsRefChika" :height="420" />
</el-card> </el-card>
</el-col> </el-col>
<!-- 内存使用量统计 -->
<el-col :span="12" class="mt-3"> <el-col :span="12" class="mt-3">
<el-card class="ml-3" :gutter="12" shadow="hover"> <el-card class="ml-3" :gutter="12" shadow="hover">
<div ref="usedmemory" class="h-88"></div> <Echart :options="usedmemoryEchartChika" :height="420" />
</el-card>
</el-col>
</el-row>
<el-row class="mt-3">
<el-col :span="24" class="card-box" shadow="hover">
<el-card>
<el-table
v-loading="keyListLoad"
:data="keyList"
row-key="id"
@row-click="openKeyTemplate"
>
<el-table-column prop="keyTemplate" label="Key 模板" width="200" />
<el-table-column prop="keyType" label="Key 类型" width="100" />
<el-table-column prop="valueType" label="Value 类型" />
<el-table-column prop="timeoutType" label="超时时间" width="200">
<template #default="{ row }">
<DictTag :type="DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE" :value="row?.timeoutType" />
<span v-if="row?.timeout > 0">({{ row?.timeout / 1000 }} )</span>
</template>
</el-table-column>
<el-table-column prop="memo" label="备注" />
</el-table>
</el-card> </el-card>
</el-col> </el-col>
</el-row> </el-row>
</el-scrollbar> </el-scrollbar>
<XModal v-model="dialogVisible" :title="keyTemplate + ' 模板'">
<el-row>
<el-col :span="14" class="mt-3">
<el-card shadow="always">
<template #header>
<div class="card-header">
<span>键名列表</span>
</div>
</template>
<el-table :data="cacheKeys" style="width: 100%" @row-click="handleKeyValue">
<el-table-column label="缓存键名" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row }}
</template>
</el-table-column>
<el-table-column label="操作" align="right" width="60">
<template #default="{ row }">
<XTextButton preIcon="ep:delete" @click="handleDeleteKey(row)" />
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :span="10" class="mt-3">
<el-card shadow="always">
<template #header>
<div class="card-header">
<span>缓存内容</span>
<XTextButton
preIcon="ep:refresh"
title="清理全部"
@click="handleDeleteKeys(keyTemplate)"
class="float-right p-1"
/>
</div>
</template>
<el-descriptions :column="1">
<el-descriptions-item label="缓存键名:">{{ cacheForm.key }}</el-descriptions-item>
<el-descriptions-item label="缓存内容:">{{ cacheForm.value }}</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
</el-row>
</XModal>
</template> </template>
<script setup lang="ts" name="Redis"> <script setup lang="ts">
import * as echarts from 'echarts' import echarts from '@/plugins/echarts'
import { DICT_TYPE } from '@/utils/dict' import { GaugeChart } from 'echarts/charts'
import { ToolboxComponent } from 'echarts/components'
import * as RedisApi from '@/api/infra/redis' import * as RedisApi from '@/api/infra/redis'
import { RedisKeyInfo, RedisMonitorInfoVO } from '@/api/infra/redis/types' import { RedisMonitorInfoVO } from '@/api/infra/redis/types'
echarts.use([ToolboxComponent])
const { t } = useI18n() // echarts.use([GaugeChart])
const message = useMessage() //
const cache = ref<RedisMonitorInfoVO>() const cache = ref<RedisMonitorInfoVO>()
const keyListLoad = ref(true)
const keyList = ref<RedisKeyInfo[]>([])
// //
const readRedisInfo = async () => { const readRedisInfo = async () => {
const data = await RedisApi.getCacheApi() const data = await RedisApi.getCache()
cache.value = data cache.value = data
loadEchartOptions(data.commandStats)
const redisKeysInfo = await RedisApi.getKeyDefineListApi()
keyList.value = redisKeysInfo
keyListLoad.value = false //
} }
//
const commandStatsRef = ref<HTMLElement>()
const usedmemory = ref<HTMLDivElement>()
const loadEchartOptions = (stats) => { // 使
const commandStats = [] as any[] const usedmemoryEchartChika = reactive({
const nameList = [] as string[] title: {
stats.forEach((row) => { //
commandStats.push({ text: '内存使用情况',
name: row.command, left: 'center',
value: row.calls show: true, // , true
}) offsetCenter: [0, '20%'], //
nameList.push(row.command) color: 'yellow', // , #333
}) fontSize: 20 // , 15
},
const commandStatsInstance = echarts.init(commandStatsRef.value!, 'macarons') toolbox: {
show: false,
commandStatsInstance.setOption({ feature: {
title: { restore: { show: true },
text: '命令统计', saveAsImage: { show: true }
left: 'center' }
}, },
tooltip: { series: [
trigger: 'item', {
formatter: '{a} <br/>{b} : {c} ({d}%)' name: '峰值',
}, type: 'gauge',
legend: { min: 0,
type: 'scroll', max: 50,
orient: 'vertical', splitNumber: 10,
right: 30, //
top: 10, color: '#F5C74E',
bottom: 20, radius: '85%',
data: nameList, center: ['50%', '50%'],
textStyle: { startAngle: 225,
color: '#a1a1a1' endAngle: -45,
axisLine: {
// 线
lineStyle: {
// lineStyle线
color: [
[0.2, '#7FFF00'],
[0.8, '#00FFFF'],
[1, '#FF0000']
],
//width: 6
width: 10
}
},
axisTick: {
//
//线5线
length: 5, // length线
lineStyle: {
// lineStyle线
color: '#76D9D7'
}
},
splitLine: {
// 线
length: 20, // length线
lineStyle: {
// lineStylelineStyle线
color: '#76D9D7'
}
},
axisLabel: {
color: '#76D9D7',
distance: 15,
fontSize: 15
},
pointer: {
//
width: 7,
show: true
},
detail: {
textStyle: {
fontWeight: 'normal',
//50
fontSize: 15,
color: '#FFFFFF'
},
valueAnimation: true
},
progress: {
show: true
} }
}, }
series: [ ]
{ })
name: '命令',
type: 'pie', // 使
radius: [20, 120], const commandStatsRefChika = reactive({
center: ['40%', '60%'], title: {
data: commandStats, text: '命令统计',
roseType: 'radius', left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
type: 'scroll',
orient: 'vertical',
right: 30,
top: 10,
bottom: 20,
data: [] as any[],
textStyle: {
color: '#a1a1a1'
}
},
series: [
{
name: '命令',
type: 'pie',
radius: [20, 120],
center: ['40%', '60%'],
data: [] as any[],
roseType: 'radius',
label: {
show: true
},
emphasis: {
label: { label: {
show: true show: true
}, },
emphasis: { itemStyle: {
label: { shadowBlur: 10,
show: true shadowOffsetX: 0,
}, shadowColor: 'rgba(0, 0, 0, 0.5)'
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
} }
} }
] }
}) ]
const usedMemoryInstance = echarts.init(usedmemory.value!, 'macarons')
usedMemoryInstance.setOption({
title: {
text: '内存使用情况',
left: 'center'
},
tooltip: {
formatter: '{b} <br/>{a} : ' + cache.value!.info.used_memory_human
},
series: [
{
name: '峰值',
type: 'gauge',
min: 0,
max: 100,
progress: {
show: true
},
detail: {
formatter: cache.value!.info.used_memory_human
},
data: [
{
value: parseFloat(cache.value!.info.used_memory_human),
name: '内存消耗'
}
]
}
]
})
}
const dialogVisible = ref(false)
const keyTemplate = ref('')
const cacheKeys = ref()
const cacheForm = ref<{
key: string
value: string
}>({
key: '',
value: ''
}) })
const openKeyTemplate = async (row: RedisKeyInfo) => {
keyTemplate.value = row.keyTemplate /** 加载数据 */
cacheKeys.value = await RedisApi.getKeyListApi(row.keyTemplate) const getSummary = () => {
dialogVisible.value = true //
initcommandStatsChart()
usedMemoryInstance()
} }
const handleDeleteKey = async (row) => {
RedisApi.deleteKeyApi(row) /** 命令使用情况 */
message.success(t('common.delSuccess')) const initcommandStatsChart = async () => {
usedmemoryEchartChika.series[0].data = []
//
try {
const data = await RedisApi.getCache()
cache.value = data
//
const commandStats = [] as any[]
const nameList = [] as string[]
data.commandStats.forEach((row) => {
commandStats.push({
name: row.command,
value: row.calls
})
nameList.push(row.command)
})
commandStatsRefChika.legend.data = nameList
commandStatsRefChika.series[0].data = commandStats
} catch {}
} }
const handleDeleteKeys = async (row) => { const usedMemoryInstance = async () => {
RedisApi.deleteKeysApi(row) try {
message.success(t('common.delSuccess')) const data = await RedisApi.getCache()
cache.value = data
//
usedmemoryEchartChika.series[0].detail = {
show: true, // , true
offsetCenter: [0, '50%'], //
color: 'auto', // , auto
fontSize: 30, // , 15
formatter: cache.value!.info.used_memory_human //
}
usedmemoryEchartChika.series[0].data[0] = {
value: cache.value!.info.used_memory_human,
name: '内存消耗'
}
usedmemoryEchartChika.tooltip = {
formatter: '{b} <br/>{a} : ' + cache.value!.info.used_memory_human
}
} catch {}
} }
const handleKeyValue = async (row) => {
const res = await RedisApi.getKeyValueApi(row) /** 初始化 **/
cacheForm.value = res onMounted(() => {
}
onBeforeMount(() => {
// TODO @hiiwbs 使 Echart
readRedisInfo() readRedisInfo()
//
getSummary()
}) })
</script> </script>