@@ -0,0 +1,186 @@ | |||
export interface RedisMonitorInfoVO { | |||
info: RedisInfoVO | |||
dbSize: number | |||
commandStats: RedisCommandStatsVO[] | |||
} | |||
export interface RedisInfoVO { | |||
io_threaded_reads_processed: string | |||
tracking_clients: string | |||
uptime_in_seconds: string | |||
cluster_connections: string | |||
current_cow_size: string | |||
maxmemory_human: string | |||
aof_last_cow_size: string | |||
master_replid2: string | |||
mem_replication_backlog: string | |||
aof_rewrite_scheduled: string | |||
total_net_input_bytes: string | |||
rss_overhead_ratio: string | |||
hz: string | |||
current_cow_size_age: string | |||
redis_build_id: string | |||
errorstat_BUSYGROUP: string | |||
aof_last_bgrewrite_status: string | |||
multiplexing_api: string | |||
client_recent_max_output_buffer: string | |||
allocator_resident: string | |||
mem_fragmentation_bytes: string | |||
aof_current_size: string | |||
repl_backlog_first_byte_offset: string | |||
tracking_total_prefixes: string | |||
redis_mode: string | |||
redis_git_dirty: string | |||
aof_delayed_fsync: string | |||
allocator_rss_bytes: string | |||
repl_backlog_histlen: string | |||
io_threads_active: string | |||
rss_overhead_bytes: string | |||
total_system_memory: string | |||
loading: string | |||
evicted_keys: string | |||
maxclients: string | |||
cluster_enabled: string | |||
redis_version: string | |||
repl_backlog_active: string | |||
mem_aof_buffer: string | |||
allocator_frag_bytes: string | |||
io_threaded_writes_processed: string | |||
instantaneous_ops_per_sec: string | |||
used_memory_human: string | |||
total_error_replies: string | |||
role: string | |||
maxmemory: string | |||
used_memory_lua: string | |||
rdb_current_bgsave_time_sec: string | |||
used_memory_startup: string | |||
used_cpu_sys_main_thread: string | |||
lazyfree_pending_objects: string | |||
aof_pending_bio_fsync: string | |||
used_memory_dataset_perc: string | |||
allocator_frag_ratio: string | |||
arch_bits: string | |||
used_cpu_user_main_thread: string | |||
mem_clients_normal: string | |||
expired_time_cap_reached_count: string | |||
unexpected_error_replies: string | |||
mem_fragmentation_ratio: string | |||
aof_last_rewrite_time_sec: string | |||
master_replid: string | |||
aof_rewrite_in_progress: string | |||
lru_clock: string | |||
maxmemory_policy: string | |||
run_id: string | |||
latest_fork_usec: string | |||
tracking_total_items: string | |||
total_commands_processed: string | |||
expired_keys: string | |||
errorstat_ERR: string | |||
used_memory: string | |||
module_fork_in_progress: string | |||
errorstat_WRONGPASS: string | |||
aof_buffer_length: string | |||
dump_payload_sanitizations: string | |||
mem_clients_slaves: string | |||
keyspace_misses: string | |||
server_time_usec: string | |||
executable: string | |||
lazyfreed_objects: string | |||
db0: string | |||
used_memory_peak_human: string | |||
keyspace_hits: string | |||
rdb_last_cow_size: string | |||
aof_pending_rewrite: string | |||
used_memory_overhead: string | |||
active_defrag_hits: string | |||
tcp_port: string | |||
uptime_in_days: string | |||
used_memory_peak_perc: string | |||
current_save_keys_processed: string | |||
blocked_clients: string | |||
total_reads_processed: string | |||
expire_cycle_cpu_milliseconds: string | |||
sync_partial_err: string | |||
used_memory_scripts_human: string | |||
aof_current_rewrite_time_sec: string | |||
aof_enabled: string | |||
process_supervised: string | |||
master_repl_offset: string | |||
used_memory_dataset: string | |||
used_cpu_user: string | |||
rdb_last_bgsave_status: string | |||
tracking_total_keys: string | |||
atomicvar_api: string | |||
allocator_rss_ratio: string | |||
client_recent_max_input_buffer: string | |||
clients_in_timeout_table: string | |||
aof_last_write_status: string | |||
mem_allocator: string | |||
used_memory_scripts: string | |||
used_memory_peak: string | |||
process_id: string | |||
master_failover_state: string | |||
errorstat_NOAUTH: string | |||
used_cpu_sys: string | |||
repl_backlog_size: string | |||
connected_slaves: string | |||
current_save_keys_total: string | |||
gcc_version: string | |||
total_system_memory_human: string | |||
sync_full: string | |||
connected_clients: string | |||
module_fork_last_cow_size: string | |||
total_writes_processed: string | |||
allocator_active: string | |||
total_net_output_bytes: string | |||
pubsub_channels: string | |||
current_fork_perc: string | |||
active_defrag_key_hits: string | |||
rdb_changes_since_last_save: string | |||
instantaneous_input_kbps: string | |||
used_memory_rss_human: string | |||
configured_hz: string | |||
expired_stale_perc: string | |||
active_defrag_misses: string | |||
used_cpu_sys_children: string | |||
number_of_cached_scripts: string | |||
sync_partial_ok: string | |||
used_memory_lua_human: string | |||
rdb_last_save_time: string | |||
pubsub_patterns: string | |||
slave_expires_tracked_keys: string | |||
redis_git_sha1: string | |||
used_memory_rss: string | |||
rdb_last_bgsave_time_sec: string | |||
os: string | |||
mem_not_counted_for_evict: string | |||
active_defrag_running: string | |||
rejected_connections: string | |||
aof_rewrite_buffer_length: string | |||
total_forks: string | |||
active_defrag_key_misses: string | |||
allocator_allocated: string | |||
aof_base_size: string | |||
instantaneous_output_kbps: string | |||
second_repl_offset: string | |||
rdb_bgsave_in_progress: string | |||
used_cpu_user_children: string | |||
total_connections_received: string | |||
migrate_cached_sockets: string | |||
} | |||
export interface RedisCommandStatsVO { | |||
command: string | |||
calls: number | |||
usec: number | |||
} | |||
export interface RedisKeyInfo { | |||
keyTemplate: string | |||
keyType: string | |||
valueType: string | |||
timeoutType: number | |||
timeout: number | |||
memo: string | |||
} | |||
@@ -0,0 +1,248 @@ | |||
import React, { useState, useEffect, useRef } from 'react'; | |||
import { Table, Tag, Card, Descriptions } from 'antd'; | |||
import type { TableColumnsType, DescriptionsProps } from 'antd'; | |||
import { Pie, Liquid, Gauge } from '@ant-design/plots'; | |||
import { t } from '@/utils/i18n'; | |||
import { useRequest } from '@/hooks/use-request'; | |||
import redisService from '@/request/service/redis'; | |||
import type { RedisKeyInfo, RedisMonitorInfoVO } from '@/models' | |||
export default () => { | |||
const [dataSource, setDataSource] = useState<RedisKeyInfo[]>([]); | |||
const [redisMonitorInfo, setRedisMonitorInfo] = useState<RedisMonitorInfoVO>(); | |||
const graphRef = useRef(null); | |||
const { runAsync: getPageApi } = useRequest(redisService.getKeyDefineListApi, { manual: true }); | |||
const { runAsync: getCache } = useRequest(redisService.getCacheApi, { manual: true }); | |||
const load = async () => { | |||
const [error, { data }] = await getPageApi(); | |||
if (!error) { | |||
setDataSource(data); | |||
} | |||
}; | |||
const loadCache = async () => { | |||
const [error, { data }] = await getCache(); | |||
if (!error) { | |||
setRedisMonitorInfo(data); | |||
graphRef.current!!.changeData(parseFloat(data.info.used_memory_human.replace("M", ''))/100) | |||
} | |||
} | |||
const columns: TableColumnsType<RedisKeyInfo> = [ | |||
{ | |||
title: 'Key模板', | |||
dataIndex: 'keyTemplate', | |||
key: 'keyTemplate', | |||
align: 'right', | |||
width: 200, | |||
}, | |||
{ | |||
title: 'Key类型', | |||
dataIndex: 'keyType', | |||
key: 'keyType', | |||
align: 'center', | |||
width: 150 | |||
}, | |||
{ | |||
title: 'Value类型', | |||
key: 'valueType', | |||
dataIndex: 'valueType', | |||
align: 'left', | |||
width: 200 | |||
}, | |||
{ | |||
title: '超时时间', | |||
key: 'timeoutType', | |||
dataIndex: 'timeoutType', | |||
width: 120, | |||
align: 'center', | |||
render: (value: number) => { | |||
return (value === 3 ? <Tag color="purple">固定超时</Tag> : <Tag color="blue">动态超时</Tag>) | |||
} | |||
}, | |||
{ | |||
title: '备注', | |||
key: 'memo', | |||
dataIndex: 'memo', | |||
align: 'left', | |||
} | |||
]; | |||
const items: DescriptionsProps['items'] = [ | |||
{ | |||
key: 'redis_version', | |||
label: 'Redis版本', | |||
children: redisMonitorInfo?.info?.redis_version, | |||
}, | |||
{ | |||
key: 'redis_mode', | |||
label: '运行模式', | |||
children: redisMonitorInfo?.info?.redis_mode == 'standalone' ? '单机' : '集群', | |||
}, | |||
{ | |||
key: 'tcp_port', | |||
label: '端口', | |||
children: redisMonitorInfo?.info?.tcp_port, | |||
}, | |||
{ | |||
key: 'connected_clients', | |||
label: '客户端数', | |||
children: redisMonitorInfo?.info?.connected_clients, | |||
}, | |||
{ | |||
key: 'uptime_in_days', | |||
label: '运行时间(天)', | |||
children: redisMonitorInfo?.info?.uptime_in_days, | |||
}, | |||
{ | |||
key: 'used_memory_human', | |||
label: '使用内存', | |||
children: redisMonitorInfo?.info?.used_memory_human, | |||
}, | |||
{ | |||
key: 'used_cpu_user_children', | |||
label: '使用CPU', | |||
children: redisMonitorInfo?.info ? parseFloat(redisMonitorInfo?.info?.used_cpu_user_children).toFixed(2) : '', | |||
}, | |||
{ | |||
key: 'maxmemory_human', | |||
label: '内存配置', | |||
children: redisMonitorInfo?.info?.maxmemory_human, | |||
}, | |||
{ | |||
key: 'aof_enabled', | |||
label: 'AOF是否开启', | |||
children: redisMonitorInfo?.info?.aof_enabled == '0' ? '否' : '是', | |||
}, | |||
{ | |||
key: 'rdb_last_bgsave_status', | |||
label: 'RDB是否成功', | |||
children: redisMonitorInfo?.info?.rdb_last_bgsave_status, | |||
}, | |||
{ | |||
key: 'dbSize', | |||
label: 'Key数量', | |||
children: redisMonitorInfo?.dbSize, | |||
}, | |||
{ | |||
key: 'instantaneous', | |||
label: '网络入口/出口', | |||
children: (<> | |||
{redisMonitorInfo?.info?.instantaneous_input_kbps} kps/{redisMonitorInfo?.info?.instantaneous_output_kbps} kps | |||
</>), | |||
}, | |||
]; | |||
const config = { | |||
appendPadding: 10, | |||
data: redisMonitorInfo?.commandStats.map(it => { | |||
return { | |||
type: it.command, | |||
value: it.usec | |||
} | |||
}) ?? [], | |||
angleField: 'value', | |||
colorField: 'type', | |||
radius: 0.8, | |||
label: { | |||
type: 'outer', | |||
content: '{name} {percentage}', | |||
}, | |||
interactions: [ | |||
{ | |||
type: 'pie-legend-active', | |||
}, | |||
{ | |||
type: 'element-active', | |||
}, | |||
], | |||
}; | |||
const ticks = [0, 1 / 3, 2 / 3, 1]; | |||
const color = ['#30BF78', '#FAAD14', '#F4664A']; | |||
const memUsage = { | |||
percent: 0, | |||
type: 'meter', | |||
innerRadius: 0.8, | |||
range: { ticks, color }, | |||
indicator: { | |||
pointer: { | |||
style: { | |||
stroke: '#D0D0D0', | |||
}, | |||
}, | |||
pin: { | |||
style: { | |||
stroke: '#D0D0D0', | |||
}, | |||
}, | |||
}, | |||
statistic: { | |||
title: { | |||
formatter: () => redisMonitorInfo?.info.used_memory_human??'0M', | |||
style: ({ percent }) => { | |||
return { | |||
fontSize: '24px', | |||
lineHeight: 1, | |||
color: percent < ticks[1] ? color[0] : percent < ticks[2] ? color[1] : color[2], | |||
}; | |||
}, | |||
}, | |||
content: { | |||
offsetY: 24, | |||
style: { | |||
fontSize: '16px', | |||
lineHeight: '16px', | |||
}, | |||
formatter: () => '内存消耗' | |||
}, | |||
}, | |||
onReady: (plot) => { | |||
graphRef.current = plot; | |||
} | |||
} | |||
useEffect(() => { | |||
load(); | |||
loadCache(); | |||
}, []); | |||
return ( | |||
<> | |||
<div> | |||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'> | |||
<Descriptions title="基本信息" | |||
bordered | |||
column={6} | |||
items={items} /> | |||
</Card> | |||
<div className='flex flex-row'> | |||
<Card className='basis-1/2 mt-[4px] mr-[8px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' | |||
title="命令统计"> | |||
<Pie {...config} /> | |||
</Card> | |||
<Card className='basis-1/2 mt-[4px] ml-[8px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' | |||
title="内存使用情况"> | |||
<Gauge {...memUsage} /> | |||
</Card> | |||
</div> | |||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]'> | |||
<Table rowKey="id" | |||
scroll={{ x: true }} | |||
columns={columns} | |||
dataSource={dataSource} | |||
className='bg-transparent' | |||
pagination={false} /> | |||
</Card> | |||
</div> | |||
</> | |||
); | |||
}; | |||
@@ -0,0 +1,39 @@ | |||
import request from '@/request'; | |||
import { RedisMonitorInfoVO, RedisInfoVO, RedisCommandStatsVO, RedisKeyInfo } from '@/models'; | |||
const BASE_URL = '/admin-api/infra/redis'; | |||
export default { | |||
/** | |||
* 获取redis 监控信息 | |||
*/ | |||
getCacheApi: () => { | |||
return request.get<RedisMonitorInfoVO>(`${BASE_URL}/get-monitor-info`) | |||
}, | |||
// 获取模块 | |||
getKeyDefineListApi: () => { | |||
return request.get<RedisKeyInfo[]>(`${BASE_URL}/get-key-define-list`) | |||
}, | |||
/** | |||
* 获取redis key列表 | |||
*/ | |||
getKeyListApi: (keyTemplate: string) => { | |||
return request.get(`${BASE_URL}/get-key-list`, { params: { keyTemplate } }) | |||
}, | |||
// 获取缓存内容 | |||
getKeyValueApi: (key: string) => { | |||
return request.get(`${BASE_URL}/get-key-value?key=${key}`) | |||
}, | |||
// 根据键名删除缓存 | |||
deleteKeyApi: (key: string) => { | |||
return request.delete(`${BASE_URL}/delete-key?key=${key}`) | |||
}, | |||
deleteKeysApi: (keyTemplate: string) => { | |||
return request.delete(`${BASE_URL}/delete-keys`, { params: { keyTemplate } }) | |||
}, | |||
} |