Build lightweight AI agent admin

This commit is contained in:
Codex
2026-06-08 18:14:59 +08:00
commit e164840f43
2530 changed files with 435693 additions and 0 deletions
@@ -0,0 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
服务器监控模块
"""
+265
View File
@@ -0,0 +1,265 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
服务器监控API(异步版本)
"""
import asyncio
from typing import Dict, Any, List, Optional
from fastapi import APIRouter
from core.server_monitor.server_info import ServerInfoCollector
from core.server_monitor.schema import (
ServerMonitorResponseSchema,
RealtimeStatsSchema,
BatteryInfoSchema,
BasicInfoSchema,
CpuInfoSchema,
MemoryInfoSchema,
DiskInfoSchema,
NetworkInfoSchema,
ProcessInfoSchema,
SystemLoadSchema,
BootTimeSchema,
UserInfoSchema,
)
router = APIRouter(prefix="/server_monitor", tags=["服务器监控"])
# 创建全局的服务器信息收集器实例
server_collector = ServerInfoCollector()
def _get_default_overview_error(error_msg: str) -> Dict[str, Any]:
"""获取默认的错误响应"""
return {
"basic_info": {
"hostname": "error",
"ip_address": "error",
"system": "error",
"platform": error_msg,
"architecture": "error",
"processor": "error",
"python_version": "error",
"machine": "error",
"node": "error",
"release": "error",
"version": "error"
},
"cpu_info": {
"physical_cores": 0,
"total_cores": 0,
"cpu_percent": 0.0,
"cpu_percent_per_core": [],
"max_frequency": 0.0,
"min_frequency": 0.0,
"current_frequency": 0.0,
"cpu_times": {},
"cpu_stats": {}
},
"memory_info": {
"virtual": {
"total": 0.0,
"available": 0.0,
"used": 0.0,
"free": 0.0,
"percent": 0.0,
"active": 0.0,
"inactive": 0.0,
"buffers": 0.0,
"cached": 0.0,
"shared": 0.0
},
"swap": {
"total": 0.0,
"used": 0.0,
"free": 0.0,
"percent": 0.0,
"sin": 0.0,
"sout": 0.0
}
},
"disk_info": {
"partitions": [],
"total_read_bytes": 0.0,
"total_write_bytes": 0.0,
"total_read_count": 0,
"total_write_count": 0
},
"network_info": {
"total": {
"bytes_sent": 0,
"bytes_recv": 0,
"packets_sent": 0,
"packets_recv": 0,
"errin": 0,
"errout": 0,
"dropin": 0,
"dropout": 0
},
"per_interface": {},
"interfaces": {},
"connections": []
},
"process_info": {
"total_processes": 0,
"top_processes": [],
"running_processes": 0,
"sleeping_processes": 0
},
"system_load": {
"load_1min": 0.0,
"load_5min": 0.0,
"load_15min": 0.0,
"cpu_count": 0
},
"boot_time": {
"boot_time": "",
"uptime_seconds": 0,
"uptime_formatted": "",
"uptime_days": 0,
"uptime_hours": 0,
"uptime_minutes": 0
},
"users_info": [],
"timestamp": ""
}
@router.get("/overview", response_model=ServerMonitorResponseSchema, summary="获取服务器完整监控信息")
async def get_server_overview():
"""获取服务器完整监控信息"""
try:
data = await asyncio.to_thread(server_collector.get_all_info)
return data
except Exception as e:
print(f"Error in get_server_overview: {e}")
return _get_default_overview_error(str(e))
@router.get("/realtime", response_model=RealtimeStatsSchema, summary="获取实时统计信息")
async def get_realtime_stats():
"""获取实时统计信息"""
try:
return await asyncio.to_thread(server_collector.get_realtime_stats)
except Exception as e:
print(f"Error in get_realtime_stats: {e}")
return {
"cpu_percent": 0.0,
"memory_percent": 0.0,
"disk_io": {"read_speed": 0, "write_speed": 0},
"network_io": {"upload_speed": 0, "download_speed": 0},
"network_total": {"bytes_sent": 0, "bytes_recv": 0, "packets_sent": 0, "packets_recv": 0},
"disk_total": {"read_bytes": 0, "write_bytes": 0, "read_count": 0, "write_count": 0},
"cpu_details": {"current_frequency": 0, "cpu_percent_per_core": []},
"memory_details": {"total": 0, "available": 0, "used": 0, "free": 0},
"system_load": {"load_1min": 0, "load_5min": 0, "load_15min": 0},
"process_stats": {"total_processes": 0, "running_processes": 0, "sleeping_processes": 0},
"process_info": {"total_processes": 0, "top_processes": [], "running_processes": 0, "sleeping_processes": 0},
"network_interfaces": {},
"network_connections": [],
"timestamp": ""
}
@router.get("/basic_info", response_model=BasicInfoSchema, summary="获取基础系统信息")
async def get_basic_info():
"""获取基础系统信息"""
try:
return await asyncio.to_thread(server_collector.get_basic_info)
except Exception as e:
return {"error": str(e)}
@router.get("/cpu_info", response_model=CpuInfoSchema, summary="获取CPU信息")
async def get_cpu_info():
"""获取CPU信息"""
try:
return await asyncio.to_thread(server_collector.get_cpu_info)
except Exception as e:
return {"error": str(e)}
@router.get("/memory_info", response_model=MemoryInfoSchema, summary="获取内存信息")
async def get_memory_info():
"""获取内存信息"""
try:
return await asyncio.to_thread(server_collector.get_memory_info)
except Exception as e:
return {"error": str(e)}
@router.get("/disk_info", response_model=DiskInfoSchema, summary="获取磁盘信息")
async def get_disk_info():
"""获取磁盘信息"""
try:
return await asyncio.to_thread(server_collector.get_disk_info)
except Exception as e:
return {"error": str(e)}
@router.get("/network_info", response_model=NetworkInfoSchema, summary="获取网络信息")
async def get_network_info():
"""获取网络信息"""
try:
return await asyncio.to_thread(server_collector.get_network_info)
except Exception as e:
return {"error": str(e)}
@router.get("/process_info", response_model=ProcessInfoSchema, summary="获取进程信息")
async def get_process_info():
"""获取进程信息"""
try:
return await asyncio.to_thread(server_collector.get_process_info)
except Exception as e:
return {"error": str(e)}
@router.get("/system_load", response_model=SystemLoadSchema, summary="获取系统负载信息")
async def get_system_load():
"""获取系统负载信息"""
try:
return await asyncio.to_thread(server_collector.get_system_load)
except Exception as e:
return {"error": str(e)}
@router.get("/boot_time", response_model=BootTimeSchema, summary="获取系统启动时间信息")
async def get_boot_time():
"""获取系统启动时间信息"""
try:
return await asyncio.to_thread(server_collector.get_boot_time)
except Exception as e:
return {"error": str(e)}
@router.get("/users_info", response_model=List[UserInfoSchema], summary="获取用户信息")
async def get_users_info():
"""获取用户信息"""
try:
return await asyncio.to_thread(server_collector.get_users_info)
except Exception as e:
return {"error": str(e)}
@router.get("/temperature_info", summary="获取温度信息")
async def get_temperature_info():
"""获取温度信息"""
try:
return await asyncio.to_thread(server_collector.get_temperature_info)
except Exception as e:
return {"error": str(e)}
@router.get("/battery_info", response_model=Optional[BatteryInfoSchema], summary="获取电池信息")
async def get_battery_info():
"""获取电池信息"""
try:
battery_info = await asyncio.to_thread(server_collector.get_battery_info)
if battery_info:
return battery_info
else:
return None
except Exception as e:
return {"error": str(e)}
@@ -0,0 +1,233 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
服务器监控Schema
"""
from typing import Dict, List, Any, Optional
from pydantic import BaseModel
class BasicInfoSchema(BaseModel):
"""基础系统信息"""
hostname: str
ip_address: str
system: str
platform: str
architecture: str
processor: str
python_version: str
machine: str
node: str
release: str
version: str
class CpuInfoSchema(BaseModel):
"""CPU信息"""
physical_cores: int
total_cores: int
cpu_percent: float
cpu_percent_per_core: List[float]
max_frequency: float
min_frequency: float
current_frequency: float
cpu_times: Dict[str, Any]
cpu_stats: Dict[str, Any]
class MemoryVirtualSchema(BaseModel):
"""虚拟内存信息"""
total: float
available: float
used: float
free: float
percent: float
active: float
inactive: float
buffers: float
cached: float
shared: float
class MemorySwapSchema(BaseModel):
"""交换内存信息"""
total: float
used: float
free: float
percent: float
sin: float
sout: float
class MemoryInfoSchema(BaseModel):
"""内存信息"""
virtual: MemoryVirtualSchema
swap: MemorySwapSchema
class DiskPartitionSchema(BaseModel):
"""磁盘分区信息"""
device: str
mountpoint: str
file_system: str
total_size: float
used: float
free: float
percent: float
class DiskInfoSchema(BaseModel):
"""磁盘信息"""
partitions: List[DiskPartitionSchema]
total_read_bytes: float
total_write_bytes: float
total_read_count: int
total_write_count: int
total_read_time: Optional[int] = None
total_write_time: Optional[int] = None
class NetworkTotalSchema(BaseModel):
"""网络总计信息"""
bytes_sent: int
bytes_recv: int
packets_sent: int
packets_recv: int
errin: int
errout: int
dropin: int
dropout: int
class NetworkInterfaceStatsSchema(BaseModel):
"""网络接口统计信息"""
bytes_sent: int
bytes_recv: int
packets_sent: int
packets_recv: int
errin: int
errout: int
dropin: int
dropout: int
class NetworkAddressSchema(BaseModel):
"""网络地址信息"""
family: str
address: str
netmask: Optional[str] = None
broadcast: Optional[str] = None
class NetworkInterfaceStatsDetailSchema(BaseModel):
"""网络接口详细统计"""
is_up: bool
duplex: str
speed: int
mtu: int
class NetworkInterfaceSchema(BaseModel):
"""网络接口信息"""
addresses: List[NetworkAddressSchema]
stats: NetworkInterfaceStatsDetailSchema
class NetworkConnectionSchema(BaseModel):
"""网络连接信息"""
local_address: str
status: str
pid: Optional[int] = None
class NetworkInfoSchema(BaseModel):
"""网络信息"""
total: NetworkTotalSchema
per_interface: Dict[str, NetworkInterfaceStatsSchema]
interfaces: Dict[str, NetworkInterfaceSchema]
connections: List[NetworkConnectionSchema]
class ProcessSchema(BaseModel):
"""进程信息"""
pid: int
name: str
cpu_percent: float
memory_percent: float
status: str
create_time: str
class ProcessInfoSchema(BaseModel):
"""进程统计信息"""
total_processes: int
top_processes: List[ProcessSchema]
running_processes: int
sleeping_processes: int
class SystemLoadSchema(BaseModel):
"""系统负载信息"""
load_1min: float
load_5min: float
load_15min: float
cpu_count: int
class BootTimeSchema(BaseModel):
"""启动时间信息"""
boot_time: str
uptime_seconds: int
uptime_formatted: str
uptime_days: int
uptime_hours: int
uptime_minutes: int
class UserInfoSchema(BaseModel):
"""用户信息"""
name: str
terminal: Optional[str] = None
host: Optional[str] = None
started: Optional[str] = None
pid: Optional[int] = None
class BatteryInfoSchema(BaseModel):
"""电池信息"""
percent: float
power_plugged: bool
seconds_left: Optional[int] = None
class RealtimeStatsSchema(BaseModel):
"""实时统计信息"""
cpu_percent: float
memory_percent: float
disk_io: Dict[str, float]
network_io: Dict[str, float]
network_total: Dict[str, int]
disk_total: Dict[str, int]
cpu_details: Dict[str, Any]
memory_details: Dict[str, float]
system_load: Dict[str, float]
process_stats: Dict[str, int]
process_info: ProcessInfoSchema
network_interfaces: Dict[str, Dict[str, int]]
network_connections: List[Dict[str, Any]]
timestamp: str
class ServerMonitorResponseSchema(BaseModel):
"""服务器监控完整响应"""
basic_info: BasicInfoSchema
cpu_info: CpuInfoSchema
memory_info: MemoryInfoSchema
disk_info: DiskInfoSchema
network_info: NetworkInfoSchema
process_info: ProcessInfoSchema
system_load: SystemLoadSchema
boot_time: BootTimeSchema
users_info: List[UserInfoSchema]
timestamp: str
@@ -0,0 +1,681 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
服务器信息收集器
"""
import platform
import socket
import time
from datetime import datetime
from typing import Dict, List, Any, Optional
import psutil
class ServerInfoCollector:
"""服务器信息收集器,支持Linux、Windows、macOS"""
def __init__(self):
self.system_name = platform.system()
self.is_windows = self.system_name == 'Windows'
self.is_linux = self.system_name == 'Linux'
self.is_macos = self.system_name == 'Darwin'
# 用于计算实时速度的缓存数据
self._last_network_io = None
self._last_network_time = None
self._last_disk_io = None
self._last_disk_time = None
# 用于CPU使用率的缓存数据
self._last_cpu_times = None
self._last_cpu_time = None
# 初始化CPU使用率监控
try:
psutil.cpu_percent(interval=None)
except:
pass
def get_all_info(self) -> Dict[str, Any]:
"""获取所有服务器监控信息"""
return {
'basic_info': self.get_basic_info(),
'cpu_info': self.get_cpu_info(),
'memory_info': self.get_memory_info(),
'disk_info': self.get_disk_info(),
'network_info': self.get_network_info(),
'process_info': self.get_process_info(),
'system_load': self.get_system_load(),
'boot_time': self.get_boot_time(),
'users_info': self.get_users_info(),
'timestamp': datetime.now().isoformat()
}
def get_basic_info(self) -> Dict[str, Any]:
"""获取基础系统信息"""
try:
hostname = socket.gethostname()
ip_address = socket.gethostbyname(hostname)
except:
hostname = "unknown"
ip_address = "unknown"
try:
return {
'hostname': hostname,
'ip_address': ip_address,
'system': platform.system(),
'platform': platform.platform(),
'architecture': platform.architecture()[0],
'processor': platform.processor() or "Unknown",
'python_version': platform.python_version(),
'machine': platform.machine(),
'node': platform.node(),
'release': platform.release(),
'version': platform.version(),
}
except Exception as e:
print(f"Error getting basic info: {e}")
return {
'hostname': hostname,
'ip_address': ip_address,
'system': "Unknown",
'platform': "Unknown",
'architecture': "Unknown",
'processor': "Unknown",
'python_version': "Unknown",
'machine': "Unknown",
'node': "Unknown",
'release': "Unknown",
'version': "Unknown",
}
def get_cpu_info(self) -> Dict[str, Any]:
"""获取CPU信息"""
try:
cpu_percent = psutil.cpu_percent(interval=1, percpu=True)
overall_cpu_percent = psutil.cpu_percent(interval=1)
try:
cpu_freq = psutil.cpu_freq()
except (FileNotFoundError, OSError):
cpu_freq = None
return {
'physical_cores': psutil.cpu_count(logical=False) or 0,
'total_cores': psutil.cpu_count(logical=True) or 0,
'cpu_percent': round(overall_cpu_percent, 2),
'cpu_percent_per_core': [round(x, 2) for x in cpu_percent] if cpu_percent else [],
'max_frequency': round(cpu_freq.max, 2) if cpu_freq and cpu_freq.max else 0,
'min_frequency': round(cpu_freq.min, 2) if cpu_freq and cpu_freq.min else 0,
'current_frequency': round(cpu_freq.current, 2) if cpu_freq and cpu_freq.current else 0,
'cpu_times': dict(psutil.cpu_times()._asdict()),
'cpu_stats': dict(psutil.cpu_stats()._asdict()) if hasattr(psutil, 'cpu_stats') else {}
}
except Exception as e:
print(f"Error getting CPU info: {e}")
return {
'physical_cores': 0,
'total_cores': 0,
'cpu_percent': 0.0,
'cpu_percent_per_core': [],
'max_frequency': 0.0,
'min_frequency': 0.0,
'current_frequency': 0.0,
'cpu_times': {},
'cpu_stats': {}
}
def get_memory_info(self) -> Dict[str, Any]:
"""获取内存信息"""
virtual_mem = psutil.virtual_memory()
swap_mem = psutil.swap_memory()
return {
'virtual': {
'total': self._bytes_to_gb(virtual_mem.total),
'available': self._bytes_to_gb(virtual_mem.available),
'used': self._bytes_to_gb(virtual_mem.used),
'free': self._bytes_to_gb(virtual_mem.free),
'percent': round(virtual_mem.percent, 2),
'active': self._bytes_to_gb(getattr(virtual_mem, 'active', 0)),
'inactive': self._bytes_to_gb(getattr(virtual_mem, 'inactive', 0)),
'buffers': self._bytes_to_gb(getattr(virtual_mem, 'buffers', 0)),
'cached': self._bytes_to_gb(getattr(virtual_mem, 'cached', 0)),
'shared': self._bytes_to_gb(getattr(virtual_mem, 'shared', 0)),
},
'swap': {
'total': self._bytes_to_gb(swap_mem.total),
'used': self._bytes_to_gb(swap_mem.used),
'free': self._bytes_to_gb(swap_mem.free),
'percent': round(swap_mem.percent, 2),
'sin': self._bytes_to_mb(swap_mem.sin),
'sout': self._bytes_to_mb(swap_mem.sout),
}
}
def get_disk_info(self) -> Dict[str, Any]:
"""获取磁盘信息"""
partitions = psutil.disk_partitions()
disk_info = {
'partitions': [],
'total_read_bytes': 0,
'total_write_bytes': 0,
'total_read_count': 0,
'total_write_count': 0,
}
try:
disk_io = psutil.disk_io_counters()
if disk_io:
disk_info.update({
'total_read_bytes': self._bytes_to_gb(disk_io.read_bytes),
'total_write_bytes': self._bytes_to_gb(disk_io.write_bytes),
'total_read_count': disk_io.read_count,
'total_write_count': disk_io.write_count,
'total_read_time': disk_io.read_time,
'total_write_time': disk_io.write_time,
})
except:
pass
for partition in partitions:
try:
partition_usage = psutil.disk_usage(partition.mountpoint)
disk_info['partitions'].append({
'device': partition.device,
'mountpoint': partition.mountpoint,
'file_system': partition.fstype,
'total_size': self._bytes_to_gb(partition_usage.total),
'used': self._bytes_to_gb(partition_usage.used),
'free': self._bytes_to_gb(partition_usage.free),
'percent': round(partition_usage.percent, 2),
})
except PermissionError:
continue
return disk_info
def get_network_info(self) -> Dict[str, Any]:
"""获取网络信息"""
network_io = psutil.net_io_counters()
per_nic = psutil.net_io_counters(pernic=True)
connections = []
try:
for conn in psutil.net_connections():
if conn.status == 'LISTEN':
connections.append({
'local_address': f"{conn.laddr.ip}:{conn.laddr.port}" if conn.laddr else "",
'status': conn.status,
'pid': conn.pid
})
except:
pass
addresses = psutil.net_if_addrs()
interface_stats = psutil.net_if_stats()
interfaces = {}
for interface_name, interface_addresses in addresses.items():
interfaces[interface_name] = {
'addresses': [],
'stats': {
'is_up': False,
'duplex': 'unknown',
'speed': 0,
'mtu': 0
}
}
for addr in interface_addresses:
interfaces[interface_name]['addresses'].append({
'family': str(addr.family),
'address': addr.address,
'netmask': addr.netmask,
'broadcast': addr.broadcast,
})
if interface_name in interface_stats:
stat = interface_stats[interface_name]
interfaces[interface_name]['stats'] = {
'is_up': stat.isup,
'duplex': str(stat.duplex),
'speed': stat.speed,
'mtu': stat.mtu,
}
return {
'total': {
'bytes_sent': network_io.bytes_sent,
'bytes_recv': network_io.bytes_recv,
'packets_sent': network_io.packets_sent,
'packets_recv': network_io.packets_recv,
'errin': network_io.errin,
'errout': network_io.errout,
'dropin': network_io.dropin,
'dropout': network_io.dropout,
},
'per_interface': {
name: {
'bytes_sent': stats.bytes_sent,
'bytes_recv': stats.bytes_recv,
'packets_sent': stats.packets_sent,
'packets_recv': stats.packets_recv,
'errin': stats.errin,
'errout': stats.errout,
'dropin': stats.dropin,
'dropout': stats.dropout,
}
for name, stats in per_nic.items()
},
'interfaces': interfaces,
'connections': connections[:50]
}
def get_process_info(self) -> Dict[str, Any]:
"""获取进程信息"""
processes = []
total_processes = 0
running_processes = 0
sleeping_processes = 0
try:
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status', 'create_time']):
try:
process_info = proc.info
total_processes += 1
status = process_info.get('status', '')
if status == psutil.STATUS_RUNNING:
running_processes += 1
elif status == psutil.STATUS_SLEEPING:
sleeping_processes += 1
cpu_percent = process_info.get('cpu_percent', 0.0)
memory_percent = process_info.get('memory_percent', 0.0)
if cpu_percent is None:
cpu_percent = 0.0
if memory_percent is None:
memory_percent = 0.0
if cpu_percent > 1.0 or memory_percent > 1.0:
create_time = process_info.get('create_time')
if create_time:
create_time_str = datetime.fromtimestamp(create_time).isoformat()
else:
create_time_str = datetime.now().isoformat()
processes.append({
'pid': process_info.get('pid', 0),
'name': process_info.get('name', 'Unknown'),
'cpu_percent': round(float(cpu_percent), 2),
'memory_percent': round(float(memory_percent), 2),
'status': status or 'Unknown',
'create_time': create_time_str,
})
except (psutil.NoSuchProcess, psutil.AccessDenied, TypeError, ValueError):
continue
processes.sort(key=lambda x: x['cpu_percent'], reverse=True)
except Exception as e:
print(f"Error getting process info: {e}")
return {
'total_processes': total_processes,
'top_processes': processes[:20],
'running_processes': running_processes,
'sleeping_processes': sleeping_processes,
}
def get_system_load(self) -> Dict[str, Any]:
"""获取系统负载信息"""
try:
if hasattr(psutil, 'getloadavg'):
try:
load_avg = psutil.getloadavg()
return {
'load_1min': round(load_avg[0], 2),
'load_5min': round(load_avg[1], 2),
'load_15min': round(load_avg[2], 2),
'cpu_count': psutil.cpu_count() or 1
}
except:
pass
cpu_percent = psutil.cpu_percent(interval=0.1)
cpu_count = psutil.cpu_count() or 1
return {
'load_1min': round(cpu_percent / 100 * cpu_count, 2),
'load_5min': round(cpu_percent / 100 * cpu_count, 2),
'load_15min': round(cpu_percent / 100 * cpu_count, 2),
'cpu_count': cpu_count
}
except Exception as e:
print(f"Error getting system load: {e}")
return {
'load_1min': 0.0,
'load_5min': 0.0,
'load_15min': 0.0,
'cpu_count': 1
}
def get_boot_time(self) -> Dict[str, Any]:
"""获取系统启动时间信息"""
try:
boot_timestamp = psutil.boot_time()
boot_datetime = datetime.fromtimestamp(boot_timestamp)
uptime_seconds = int(time.time() - boot_timestamp)
days = uptime_seconds // 86400
hours = (uptime_seconds % 86400) // 3600
minutes = (uptime_seconds % 3600) // 60
return {
'boot_time': boot_datetime.isoformat(),
'uptime_seconds': uptime_seconds,
'uptime_formatted': f"{days}{hours}小时 {minutes}分钟",
'uptime_days': days,
'uptime_hours': hours,
'uptime_minutes': minutes,
}
except Exception as e:
print(f"Error getting boot time: {e}")
return {
'boot_time': datetime.now().isoformat(),
'uptime_seconds': 0,
'uptime_formatted': "0天 0小时 0分钟",
'uptime_days': 0,
'uptime_hours': 0,
'uptime_minutes': 0,
}
def get_users_info(self) -> List[Dict[str, Any]]:
"""获取用户信息"""
users = []
try:
for user in psutil.users():
users.append({
'name': user.name,
'terminal': user.terminal,
'host': user.host,
'started': datetime.fromtimestamp(user.started).isoformat() if user.started else None,
'pid': getattr(user, 'pid', None),
})
except:
pass
return users
def get_temperature_info(self) -> Dict[str, Any]:
"""获取温度信息(如果支持的话)"""
temps = {}
try:
if hasattr(psutil, 'sensors_temperatures'):
sensors = psutil.sensors_temperatures()
for name, entries in sensors.items():
temps[name] = []
for entry in entries:
temps[name].append({
'label': entry.label,
'current': entry.current,
'high': entry.high,
'critical': entry.critical,
})
except:
pass
return temps
def get_battery_info(self) -> Optional[Dict[str, Any]]:
"""获取电池信息(适用于笔记本电脑)"""
try:
if hasattr(psutil, 'sensors_battery'):
battery = psutil.sensors_battery()
if battery:
return {
'percent': battery.percent,
'power_plugged': battery.power_plugged,
'seconds_left': battery.secsleft if battery.secsleft != psutil.POWER_TIME_UNLIMITED else None,
}
except:
pass
return None
def _bytes_to_gb(self, bytes_value: int) -> float:
"""将字节转换为GB"""
return round(bytes_value / (1024 ** 3), 2)
def _bytes_to_mb(self, bytes_value: int) -> float:
"""将字节转换为MB"""
return round(bytes_value / (1024 ** 2), 2)
def get_realtime_stats(self) -> Dict[str, Any]:
"""获取实时统计信息(用于实时更新)"""
current_time = time.time()
# 获取当前网络IO统计
current_network_io = psutil.net_io_counters()
upload_speed = 0.0
download_speed = 0.0
if (self._last_network_io is not None and
self._last_network_time is not None and
current_network_io is not None):
time_diff = current_time - self._last_network_time
if time_diff > 0:
bytes_sent_diff = current_network_io.bytes_sent - self._last_network_io.bytes_sent
bytes_recv_diff = current_network_io.bytes_recv - self._last_network_io.bytes_recv
upload_speed = max(0, bytes_sent_diff / time_diff)
download_speed = max(0, bytes_recv_diff / time_diff)
if current_network_io:
self._last_network_io = current_network_io
self._last_network_time = current_time
# 获取当前磁盘IO统计
current_disk_io = psutil.disk_io_counters()
read_speed = 0.0
write_speed = 0.0
if (self._last_disk_io is not None and
self._last_disk_time is not None and
current_disk_io is not None):
time_diff = current_time - self._last_disk_time
if time_diff > 0:
read_bytes_diff = current_disk_io.read_bytes - self._last_disk_io.read_bytes
write_bytes_diff = current_disk_io.write_bytes - self._last_disk_io.write_bytes
read_speed = max(0, read_bytes_diff / time_diff)
write_speed = max(0, write_bytes_diff / time_diff)
if current_disk_io:
self._last_disk_io = current_disk_io
self._last_disk_time = current_time
# 获取CPU详细信息
cpu_percent_per_core = psutil.cpu_percent(interval=None, percpu=True)
overall_cpu_percent = psutil.cpu_percent(interval=None)
if overall_cpu_percent == 0.0 and cpu_percent_per_core and not all(
core == 0.0 for core in cpu_percent_per_core):
overall_cpu_percent = sum(cpu_percent_per_core) / len(cpu_percent_per_core)
elif overall_cpu_percent == 0.0 and all(core == 0.0 for core in cpu_percent_per_core):
try:
overall_cpu_percent = psutil.cpu_percent(interval=0.1)
cpu_percent_per_core = psutil.cpu_percent(interval=0.1, percpu=True)
except:
pass
try:
cpu_freq = psutil.cpu_freq()
except (FileNotFoundError, OSError):
cpu_freq = None
# 获取内存详细信息
virtual_mem = psutil.virtual_memory()
# 获取系统负载
load_info = {}
try:
if hasattr(psutil, 'getloadavg'):
try:
load_avg = psutil.getloadavg()
load_info = {
'load_1min': round(load_avg[0], 2),
'load_5min': round(load_avg[1], 2),
'load_15min': round(load_avg[2], 2),
}
except:
pass
if not load_info:
cpu_percent = psutil.cpu_percent(interval=0.1)
cpu_count = psutil.cpu_count() or 1
load_info = {
'load_1min': round(cpu_percent / 100 * cpu_count, 2),
'load_5min': round(cpu_percent / 100 * cpu_count, 2),
'load_15min': round(cpu_percent / 100 * cpu_count, 2),
}
except:
load_info = {
'load_1min': 0.0,
'load_5min': 0.0,
'load_15min': 0.0,
}
# 获取进程统计信息
total_processes = 0
running_processes = 0
sleeping_processes = 0
top_processes = []
try:
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status', 'create_time']):
try:
process_info = proc.info
total_processes += 1
status = process_info.get('status', '')
if status == psutil.STATUS_RUNNING:
running_processes += 1
elif status == psutil.STATUS_SLEEPING:
sleeping_processes += 1
cpu_percent = process_info.get('cpu_percent', 0.0)
memory_percent = process_info.get('memory_percent', 0.0)
if cpu_percent is None:
cpu_percent = 0.0
if memory_percent is None:
memory_percent = 0.0
if cpu_percent > 0.5 or memory_percent > 0.5:
create_time = process_info.get('create_time')
if create_time:
create_time_str = datetime.fromtimestamp(create_time).isoformat()
else:
create_time_str = datetime.now().isoformat()
top_processes.append({
'pid': process_info.get('pid', 0),
'name': process_info.get('name', 'Unknown'),
'cpu_percent': round(float(cpu_percent), 2),
'memory_percent': round(float(memory_percent), 2),
'status': status or 'Unknown',
'create_time': create_time_str,
})
except (psutil.NoSuchProcess, psutil.AccessDenied, TypeError, ValueError):
continue
top_processes.sort(key=lambda x: x['cpu_percent'], reverse=True)
top_processes = top_processes[:15]
except Exception as e:
print(f"Error getting process info in realtime: {e}")
# 获取网络接口详细统计
per_nic = psutil.net_io_counters(pernic=True)
per_interface_stats = {}
for name, stats in per_nic.items():
per_interface_stats[name] = {
'bytes_sent': stats.bytes_sent,
'bytes_recv': stats.bytes_recv,
'packets_sent': stats.packets_sent,
'packets_recv': stats.packets_recv,
'errin': stats.errin,
'errout': stats.errout,
'dropin': stats.dropin,
'dropout': stats.dropout,
}
# 获取网络连接
connections = []
try:
for conn in psutil.net_connections():
if conn.status == 'LISTEN':
connections.append({
'local_address': f"{conn.laddr.ip}:{conn.laddr.port}" if conn.laddr else "",
'status': conn.status,
'pid': conn.pid
})
if len(connections) >= 50:
break
except:
pass
return {
'cpu_percent': round(overall_cpu_percent, 2),
'memory_percent': round(virtual_mem.percent, 2),
'disk_io': {
'read_speed': read_speed,
'write_speed': write_speed,
},
'network_io': {
'upload_speed': upload_speed,
'download_speed': download_speed,
},
'network_total': {
'bytes_sent': current_network_io.bytes_sent if current_network_io else 0,
'bytes_recv': current_network_io.bytes_recv if current_network_io else 0,
'packets_sent': current_network_io.packets_sent if current_network_io else 0,
'packets_recv': current_network_io.packets_recv if current_network_io else 0,
},
'disk_total': {
'read_bytes': current_disk_io.read_bytes if current_disk_io else 0,
'write_bytes': current_disk_io.write_bytes if current_disk_io else 0,
'read_count': current_disk_io.read_count if current_disk_io else 0,
'write_count': current_disk_io.write_count if current_disk_io else 0,
},
'cpu_details': {
'current_frequency': round(cpu_freq.current, 2) if cpu_freq and cpu_freq.current else 0,
'cpu_percent_per_core': [round(x, 2) for x in cpu_percent_per_core] if cpu_percent_per_core else [],
},
'memory_details': {
'total': self._bytes_to_gb(virtual_mem.total),
'available': self._bytes_to_gb(virtual_mem.available),
'used': self._bytes_to_gb(virtual_mem.used),
'free': self._bytes_to_gb(virtual_mem.free),
},
'system_load': load_info,
'process_stats': {
'total_processes': total_processes,
'running_processes': running_processes,
'sleeping_processes': sleeping_processes,
},
'process_info': {
'total_processes': total_processes,
'top_processes': top_processes,
'running_processes': running_processes,
'sleeping_processes': sleeping_processes,
},
'network_interfaces': per_interface_stats,
'network_connections': connections,
'timestamp': datetime.now().isoformat()
}