From 093788acea90e0758ceaa4e32011fdd82359a202 Mon Sep 17 00:00:00 2001 From: Wu Clan Date: Fri, 30 Jan 2026 16:45:22 +0800 Subject: [PATCH] Update redis and server health monitor data (#1051) * Update redis and server health monitor data * Update uptime --- backend/app/admin/api/v1/monitor/redis.py | 16 ++++--- backend/app/admin/api/v1/monitor/server.py | 16 +++---- backend/app/admin/schema/monitor.py | 54 ++++++++++++---------- backend/utils/format.py | 12 ++--- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/backend/app/admin/api/v1/monitor/redis.py b/backend/app/admin/api/v1/monitor/redis.py index 54234af1..86f4c9b3 100644 --- a/backend/app/admin/api/v1/monitor/redis.py +++ b/backend/app/admin/api/v1/monitor/redis.py @@ -9,24 +9,26 @@ from backend.utils.format import fmt_seconds router = APIRouter() -@router.get('', summary='redis 监控', dependencies=[DependsJwtAuth]) +@router.get('', summary='Redis 监控', dependencies=[DependsJwtAuth]) async def get_redis_info() -> ResponseSchemaModel[RedisMonitorInfo]: info = await redis_client.info() db_size = await redis_client.dbsize() - uptime_formatted = fmt_seconds(int(info.get('uptime_in_seconds', 0))) - server_info = RedisServerInfo( redis_version=str(info.get('redis_version', '')), redis_mode=str(info.get('redis_mode', '')), - os=str(info.get('os', '')), - arch_bits=str(info.get('arch_bits', '')), + role=str(info.get('role', '')), tcp_port=str(info.get('tcp_port', '')), - uptime_in_seconds=uptime_formatted, + uptime=str(fmt_seconds(int(info.get('uptime_in_seconds', 0)))), connected_clients=str(info.get('connected_clients', '')), + blocked_clients=str(info.get('blocked_clients', '')), used_memory_human=str(info.get('used_memory_human', '')), - used_memory_peak_human=str(info.get('used_memory_peak_human', '')), + used_memory_rss_human=str(info.get('used_memory_rss_human', '')), maxmemory_human=str(info.get('maxmemory_human', '0B')), + mem_fragmentation_ratio=str(info.get('mem_fragmentation_ratio', '0')), + instantaneous_ops_per_sec=str(info.get('instantaneous_ops_per_sec', '')), + total_commands_processed=str(info.get('total_commands_processed', '')), + rejected_connections=str(info.get('rejected_connections', '')), keys_num=str(db_size), ) diff --git a/backend/app/admin/api/v1/monitor/server.py b/backend/app/admin/api/v1/monitor/server.py index 2b0b80dc..9e4104c9 100644 --- a/backend/app/admin/api/v1/monitor/server.py +++ b/backend/app/admin/api/v1/monitor/server.py @@ -27,17 +27,17 @@ from backend.utils.timezone import timezone router = APIRouter() -@router.get('', summary='server 监控', dependencies=[DependsJwtAuth]) +@router.get('', summary='Server 监控', dependencies=[DependsJwtAuth]) async def get_server_info() -> ResponseSchemaModel[ServerMonitorInfo]: # noqa: C901 def get_all_info() -> ServerMonitorInfo: # noqa: C901 # CPU 信息 cpu_data = { - 'usage': round(psutil.cpu_percent(interval=0.1), 2), - 'logical_num': psutil.cpu_count(logical=True) or 0, 'physical_num': psutil.cpu_count(logical=False) or 0, + 'logical_num': psutil.cpu_count(logical=True) or 0, 'max_freq': 0.0, 'min_freq': 0.0, 'current_freq': 0.0, + 'usage': round(psutil.cpu_percent(interval=0.1), 2), } try: @@ -74,7 +74,7 @@ async def get_server_info() -> ResponseSchemaModel[ServerMonitorInfo]: # noqa: ip = s.getsockname()[0] except (TimeoutError, socket.gaierror, OSError): pass - sys_info = SysInfo(name=hostname, ip=ip, os=platform.system(), arch=platform.machine()) + sys_info = SysInfo(name=hostname, os=platform.system(), ip=ip, arch=platform.machine()) # 磁盘信息 disk_list = [] @@ -94,11 +94,11 @@ async def get_server_info() -> ResponseSchemaModel[ServerMonitorInfo]: # noqa: disk_list.append( DiskInfo( dir=partition.mountpoint, - type=partition.fstype, device=partition.device, + type=partition.fstype, total=fmt_bytes(usage.total), - free=fmt_bytes(usage.free), used=fmt_bytes(usage.used), + free=fmt_bytes(usage.free), usage=f'{usage.percent:.2f}%', ) ) @@ -120,12 +120,12 @@ async def get_server_info() -> ResponseSchemaModel[ServerMonitorInfo]: # noqa: name='Python3', version=platform.python_version(), home=sys.executable, + startup=timezone.to_str(start_time), + elapsed=elapsed, cpu_usage=f'{process.cpu_percent(interval=0.1):.2f}%', mem_vms=fmt_bytes(proc_mem.vms), mem_rss=fmt_bytes(proc_mem.rss), mem_free=fmt_bytes(proc_mem.vms - proc_mem.rss), - startup=timezone.to_str(start_time), - elapsed=elapsed, ) return ServerMonitorInfo(cpu=cpu, mem=mem_info, sys=sys_info, disk=disk_list, service=service) diff --git a/backend/app/admin/schema/monitor.py b/backend/app/admin/schema/monitor.py index 28f1f3d8..170ed6b4 100644 --- a/backend/app/admin/schema/monitor.py +++ b/backend/app/admin/schema/monitor.py @@ -6,29 +6,29 @@ from backend.common.schema import SchemaBase class CpuInfo(SchemaBase): """CPU 信息""" - usage: float = Field(description='CPU 使用率 (%)') - logical_num: int = Field(description='逻辑核心数') physical_num: int = Field(description='物理核心数') - max_freq: float = Field(description='最大频率 (MHz)') - min_freq: float = Field(description='最小频率 (MHz)') - current_freq: float = Field(description='当前频率 (MHz)') + logical_num: int = Field(description='逻辑核心数') + max_freq: float = Field(description='最大频率(MHz)') + min_freq: float = Field(description='最小频率(MHz)') + current_freq: float = Field(description='当前频率(MHz)') + usage: float = Field(description='使用率(%)') class MemInfo(SchemaBase): """内存信息""" - total: float = Field(description='总内存 (GB)') - used: float = Field(description='已使用内存 (GB)') - free: float = Field(description='可用内存 (GB)') - usage: float = Field(description='内存使用率 (%)') + total: float = Field(description='总容量(GB)') + used: float = Field(description='已使用(GB)') + free: float = Field(description='可用(GB)') + usage: float = Field(description='使用率(%)') class SysInfo(SchemaBase): """系统信息""" name: str = Field(description='主机名') - ip: str = Field(description='IP 地址') os: str = Field(description='操作系统') + ip: str = Field(description='IP 地址') arch: str = Field(description='系统架构') @@ -36,26 +36,26 @@ class DiskInfo(SchemaBase): """磁盘信息""" dir: str = Field(description='挂载点') - type: str = Field(description='文件系统类型') device: str = Field(description='设备名称') + type: str = Field(description='文件系统类型') total: str = Field(description='总容量') - free: str = Field(description='可用容量') - used: str = Field(description='已使用容量') - usage: str = Field(description='使用率') + used: str = Field(description='已使用') + free: str = Field(description='可用') + usage: str = Field(description='使用率(%)') class ServiceInfo(SchemaBase): - """服务信息""" + """服务进程信息""" name: str = Field(description='服务名称') version: str = Field(description='版本') home: str = Field(description='安装路径') + startup: str = Field(description='启动时间') + elapsed: str = Field(description='运行时长') cpu_usage: str = Field(description='CPU 使用率') mem_vms: str = Field(description='虚拟内存') mem_rss: str = Field(description='物理内存') mem_free: str = Field(description='可用内存') - startup: str = Field(description='启动时间') - elapsed: str = Field(description='运行时长') class ServerMonitorInfo(SchemaBase): @@ -64,23 +64,27 @@ class ServerMonitorInfo(SchemaBase): cpu: CpuInfo = Field(description='CPU 信息') mem: MemInfo = Field(description='内存信息') sys: SysInfo = Field(description='系统信息') - disk: list[DiskInfo] = Field(description='磁盘信息列表') + disk: list[DiskInfo] = Field(description='磁盘信息') service: ServiceInfo = Field(description='服务信息') class RedisServerInfo(SchemaBase): """Redis 服务器信息""" - redis_version: str = Field(description='Redis 版本') + redis_version: str = Field(description='版本号') redis_mode: str = Field(description='运行模式') - os: str = Field(description='操作系统') - arch_bits: str = Field(description='架构位数') - tcp_port: str = Field(description='TCP 端口') - uptime_in_seconds: str = Field(description='运行时长') + role: str = Field(description='节点角色') + tcp_port: str = Field(description='监听端口') + uptime: str = Field(description='运行时长') connected_clients: str = Field(description='已连接客户端数') + blocked_clients: str = Field(description='阻塞客户端数') used_memory_human: str = Field(description='已使用内存') - used_memory_peak_human: str = Field(description='内存使用峰值') + used_memory_rss_human: str = Field(description='RSS 内存') maxmemory_human: str = Field(description='最大内存限制') + mem_fragmentation_ratio: str = Field(description='内存碎片率') + instantaneous_ops_per_sec: str = Field(description='每秒操作数') + total_commands_processed: str = Field(description='命令处理总数') + rejected_connections: str = Field(description='拒绝连接数') keys_num: str = Field(description='键总数') @@ -95,4 +99,4 @@ class RedisMonitorInfo(SchemaBase): """Redis 监控信息""" info: RedisServerInfo = Field(description='服务器信息') - stats: list[RedisCommandStat] = Field(description='命令统计列表') + stats: list[RedisCommandStat] = Field(description='命令统计') diff --git a/backend/utils/format.py b/backend/utils/format.py index 5c2fb729..662cbadf 100644 --- a/backend/utils/format.py +++ b/backend/utils/format.py @@ -2,17 +2,15 @@ def fmt_seconds(seconds: int) -> str: """格式化秒数为可读的时间字符串""" days, rem = divmod(int(seconds), 86400) hours, rem = divmod(rem, 3600) - minutes, secs = divmod(rem, 60) + minutes, _ = divmod(rem, 60) parts = [] if days: - parts.append(f'{days} 天') + parts.append(f'{days} days') if hours: - parts.append(f'{hours} 小时') + parts.append(f'{hours} hours') if minutes: - parts.append(f'{minutes} 分钟') - if secs: - parts.append(f'{secs} 秒') - return ' '.join(parts) if parts else '0 秒' + parts.append(f'{minutes} minutes') + return ' '.join(parts) if parts else '0 seconds' def fmt_bytes(size: float) -> str: