#!/usr/bin/env python3 """ 系统资源监控 API 路由 """ import os import subprocess import time from flask import jsonify from utils import log_message, get_cpu_temperatures, load_alert_config try: import psutil HAS_PSUTIL = True _last_net_stats = {'bytes_sent': 0, 'bytes_recv': 0, 'time': 0} except ImportError: HAS_PSUTIL = False def register_system_routes(app): """注册系统监控相关路由""" @app.route('/api/system/stats') def api_system_stats(): """获取系统资源信息""" if not HAS_PSUTIL: return jsonify({'error': 'psutil未安装', 'available': False}) try: # CPU cpu_percent = psutil.cpu_percent(interval=0.5) cpu_count = psutil.cpu_count(logical=False) or psutil.cpu_count() cpu_count_logical = psutil.cpu_count(logical=True) # CPU 温度 cpu_temps = get_cpu_temperatures() # 内存 mem = psutil.virtual_memory() mem_total_gb = round(mem.total / (1024**3), 2) mem_used_gb = round(mem.used / (1024**3), 2) mem_available_gb = round(mem.available / (1024**3), 2) mem_percent = mem.percent # 磁盘 disk = psutil.disk_usage('/') disk_total_gb = round(disk.total / (1024**3), 2) disk_used_gb = round(disk.used / (1024**3), 2) disk_percent = disk.percent # 网速(需要计算差值) global _last_net_stats current_time = time.time() net = psutil.net_io_counters() if _last_net_stats['time'] > 0: time_diff = current_time - _last_net_stats['time'] bytes_sent_diff = net.bytes_sent - _last_net_stats['bytes_sent'] bytes_recv_diff = net.bytes_recv - _last_net_stats['bytes_recv'] upload_speed = (bytes_sent_diff / time_diff) / 1024 # KB/s download_speed = (bytes_recv_diff / time_diff) / 1024 # KB/s else: upload_speed = 0 download_speed = 0 _last_net_stats = { 'bytes_sent': net.bytes_sent, 'bytes_recv': net.bytes_recv, 'time': current_time } # 进程数量 process_count = len(psutil.pids()) # 系统启动时间 boot_time = psutil.boot_time() uptime_seconds = time.time() - boot_time uptime_hours = int(uptime_seconds // 3600) uptime_days = int(uptime_hours // 24) uptime_str = f"{uptime_days}天 {uptime_hours % 24}小时" return jsonify({ 'available': True, 'cpu': { 'percent': cpu_percent, 'count_physical': cpu_count, 'count_logical': cpu_count_logical, 'temp_package_0': cpu_temps.get('package_0'), 'temp_package_1': cpu_temps.get('package_1') }, 'memory': { 'total_gb': mem_total_gb, 'used_gb': mem_used_gb, 'available_gb': mem_available_gb, 'percent': mem_percent }, 'disk': { 'total_gb': disk_total_gb, 'used_gb': disk_used_gb, 'percent': disk_percent }, 'network': { 'upload_speed_kb': round(upload_speed, 2), 'download_speed_kb': round(download_speed, 2) }, 'process_count': process_count, 'uptime': uptime_str }) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/api/system/processes') def api_system_processes(): """获取进程列表""" if not HAS_PSUTIL: return jsonify({'error': 'psutil未安装'}), 500 try: processes = [] for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status']): try: processes.append({ 'pid': proc.info['pid'], 'name': proc.info['name'], 'cpu': proc.info['cpu_percent'] or 0, 'memory': proc.info['memory_percent'] or 0, 'status': proc.info['status'] }) except: pass # 按CPU排序 processes.sort(key=lambda x: x['cpu'], reverse=True) processes = processes[:50] # 只返回前50个 return jsonify({'processes': processes}) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/api/system/docker') def api_system_docker(): """获取 Docker 容器状态""" try: result = subprocess.run(['docker', 'ps', '--format', '{{.Names}}|{{.Status}}|{{.Ports}}'], capture_output=True, text=True, timeout=5) containers = [] for line in result.stdout.strip().split('\n'): if line: parts = line.split('|') if len(parts) >= 2: containers.append({ 'name': parts[0], 'status': parts[1], 'ports': parts[2] if len(parts) > 2 else '' }) return jsonify({'containers': containers}) except Exception as e: return jsonify({'error': str(e), 'containers': []}) @app.route('/api/alerts', methods=['GET']) def api_get_alerts(): """获取预警配置""" config = load_alert_config() return jsonify(config) @app.route('/api/alerts', methods=['POST']) def api_save_alerts(): """保存预警配置""" from flask import request import json from config import ALERT_CONFIG_FILE try: data = request.get_json() config = load_alert_config() if 'thresholds' in data: config['thresholds'] = data['thresholds'] if 'web_settings' in data: config['web_settings'] = data['web_settings'] with open(ALERT_CONFIG_FILE, 'w', encoding='utf-8') as f: json.dump(config, f, ensure_ascii=False, indent=2) return jsonify({'message': '保存成功'}) except Exception as e: return jsonify({'error': str(e)}), 500