diff --git a/src/models/redis.data.ts b/src/models/redis.data.ts new file mode 100644 index 0000000..596cabd --- /dev/null +++ b/src/models/redis.data.ts @@ -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 + } + \ No newline at end of file diff --git a/src/pages/infra/redis/index.tsx b/src/pages/infra/redis/index.tsx new file mode 100644 index 0000000..6c0ef82 --- /dev/null +++ b/src/pages/infra/redis/index.tsx @@ -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([]); + const [redisMonitorInfo, setRedisMonitorInfo] = useState(); + 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 = [ + { + 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 ? 固定超时 : 动态超时) + } + }, + { + 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 ( + <> +
+ + + + +
+ + + + + + + +
+ + + + + + + ); +}; + diff --git a/src/request/service/redis.ts b/src/request/service/redis.ts new file mode 100644 index 0000000..da6a2be --- /dev/null +++ b/src/request/service/redis.ts @@ -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(`${BASE_URL}/get-monitor-info`) + }, + // 获取模块 + getKeyDefineListApi: () => { + return request.get(`${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 } }) + }, + +}