pms-front-react/src/pages/monitor/CacheMonitorPage.tsx

146 lines
5.2 KiB
TypeScript

import { useState, useEffect } from 'react';
import { Row, Col, Card, Descriptions, Spin, message, Typography } from 'antd';
import ReactEChartsCore from 'echarts-for-react/lib/core';
import { echarts } from '@/utils/echarts';
import { macarons } from '../../themes/macarons';
import { getCache } from '../../api/monitor/cache';
import type { CacheMonitorResponse } from '@/types/api';
import './cache-monitor.css';
const { Text } = Typography;
echarts.registerTheme('macarons', macarons);
const defaultCacheData: CacheMonitorResponse = {
info: {},
dbSize: 0,
commandStats: [],
};
const toDisplayText = (value: string | number | undefined): string => {
if (value === undefined || value === null) {
return '';
}
return String(value);
};
const CacheMonitorPage = () => {
const [loading, setLoading] = useState(true);
const [cacheData, setCacheData] = useState<CacheMonitorResponse>(defaultCacheData);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
getCache()
.then((response) => {
setCacheData(response);
})
.catch(() => {
const errorMsg = '加载缓存数据失败,请确认后端服务是否正常。';
setError(errorMsg);
message.error(errorMsg);
})
.finally(() => {
setLoading(false);
});
}, []);
if (loading) {
return <Spin spinning={true} description="正在加载缓存监控数据..." style={{ display: 'block', marginTop: '50px' }} />;
}
if (error) {
return <div style={{ textAlign: 'center', marginTop: '50px' }}><Text type="danger">{error}</Text></div>;
}
const commandStatsOptions = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)',
},
series: [
{
name: '命令',
type: 'pie',
roseType: 'radius',
radius: [15, 95],
center: ['50%', '38%'],
data: cacheData.commandStats || [],
animationEasing: 'cubicInOut',
animationDuration: 1000,
},
],
};
const usedMemoryOptions = {
tooltip: {
formatter: `{b} <br/>{a} : ${toDisplayText(cacheData.info?.used_memory_human)}`,
},
series: [
{
name: '峰值',
type: 'gauge',
min: 0,
max: 1000,
detail: {
formatter: toDisplayText(cacheData.info?.used_memory_human),
},
data: [
{
value: Number.parseFloat(toDisplayText(cacheData.info?.used_memory_human)) || 0,
name: '内存消耗',
},
],
},
],
};
return (
<div className="app-container cache-monitor-container">
<Row gutter={[16, 16]}>
<Col span={24} className="card-box">
<Card title="基本信息">
<Descriptions bordered column={4}>
<Descriptions.Item label="Redis版本">{toDisplayText(cacheData.info?.redis_version)}</Descriptions.Item>
<Descriptions.Item label="运行模式">
{cacheData.info?.redis_mode === 'standalone' ? '单机' : toDisplayText(cacheData.info?.redis_mode)}
</Descriptions.Item>
<Descriptions.Item label="端口">{toDisplayText(cacheData.info?.tcp_port)}</Descriptions.Item>
<Descriptions.Item label="客户端数">{toDisplayText(cacheData.info?.connected_clients)}</Descriptions.Item>
<Descriptions.Item label="运行时间(天)">{toDisplayText(cacheData.info?.uptime_in_days)}</Descriptions.Item>
<Descriptions.Item label="使用内存">{toDisplayText(cacheData.info?.used_memory_human)}</Descriptions.Item>
<Descriptions.Item label="使用CPU">
{cacheData.info?.used_cpu_user_children
? Number.parseFloat(toDisplayText(cacheData.info.used_cpu_user_children)).toFixed(2)
: ''}
</Descriptions.Item>
<Descriptions.Item label="内存配置">{toDisplayText(cacheData.info?.maxmemory_human)}</Descriptions.Item>
<Descriptions.Item label="AOF是否开启">
{cacheData.info?.aof_enabled === '0' ? '否' : (cacheData.info?.aof_enabled ? '是' : '')}
</Descriptions.Item>
<Descriptions.Item label="RDB是否成功">{toDisplayText(cacheData.info?.rdb_last_bgsave_status)}</Descriptions.Item>
<Descriptions.Item label="Key数量">{cacheData.dbSize || ''}</Descriptions.Item>
<Descriptions.Item label="网络入口/出口">
{cacheData.info?.instantaneous_input_kbps
? `${cacheData.info.instantaneous_input_kbps}kps/${cacheData.info.instantaneous_output_kbps}kps`
: ''}
</Descriptions.Item>
</Descriptions>
</Card>
</Col>
<Col span={12} className="card-box">
<Card title="命令统计">
<ReactEChartsCore echarts={echarts} theme="macarons" option={commandStatsOptions} style={{ height: '420px' }} />
</Card>
</Col>
<Col span={12} className="card-box">
<Card title="内存信息">
<ReactEChartsCore echarts={echarts} theme="macarons" option={usedMemoryOptions} style={{ height: '420px' }} />
</Card>
</Col>
</Row>
</div>
);
};
export default CacheMonitorPage;