ProyectoPSP/monitor_logic.py

117 lines
5.4 KiB
Python

# monitor_logic.py
import psutil
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import os
# --- Variables Globales y Estado Inicial ---
MAX_SAMPLES = 60
historical_data = {
'time': list(range(1, MAX_SAMPLES + 1)),
'cpu': [0] * MAX_SAMPLES,
'memory': [0] * MAX_SAMPLES,
'disk': [0] * MAX_SAMPLES,
'net_sent': [0] * MAX_SAMPLES,
'net_recv': [0] * MAX_SAMPLES
}
LAST_NET_COUNTERS = psutil.net_io_counters()
CURRENT_PROCESS = psutil.Process(os.getpid())
def initialize_monitor_figures():
"""
Define y devuelve los objetos de figura, ejes y líneas de Matplotlib.
Esto permite inicializar el monitor una sola vez al inicio.
"""
# --- Gráfico de Uso del Sistema (CPU, Memoria, Disco) ---
fig_usage = Figure(figsize=(4, 6), dpi=100)
fig_usage.subplots_adjust(hspace=0.5)
ax1 = fig_usage.add_subplot(311)
line_cpu, = ax1.plot(historical_data['time'], historical_data['cpu'], 'r-')
ax1.set_title("Uso de CPU (%)", fontsize=10); ax1.set_ylabel("CPU (%)", fontsize=8); ax1.set_ylim(0, 100); ax1.set_xlim(1, MAX_SAMPLES); ax1.grid(True); ax1.tick_params(axis='x', labelbottom=False)
ax2 = fig_usage.add_subplot(312, sharex=ax1)
line_mem, = ax2.plot(historical_data['time'], historical_data['memory'], 'b-')
ax2.set_title("Uso de Memoria (%)", fontsize=10); ax2.set_ylabel("Memoria (%)", fontsize=8); ax2.set_ylim(0, 100); ax2.set_xlim(1, MAX_SAMPLES); ax2.grid(True); ax2.tick_params(axis='x', labelbottom=False)
ax3 = fig_usage.add_subplot(313, sharex=ax1)
line_disk, = ax3.plot(historical_data['time'], historical_data['disk'], 'g-')
ax3.set_title("Uso de Disco (%)", fontsize=10); ax3.set_xlabel("Tiempo (segundos)", fontsize=8); ax3.set_ylabel("Disco (%)", fontsize=8); ax3.set_ylim(0, 100); ax3.set_xlim(1, MAX_SAMPLES); ax3.grid(True)
fig_usage.tight_layout(pad=1.5)
# --- Gráfico de Red (Bytes Enviados/Recibidos) ---
fig_net = Figure(figsize=(4, 6), dpi=100)
fig_net.subplots_adjust(hspace=0.5)
ax_net = fig_net.add_subplot(111)
line_net_sent, = ax_net.plot(historical_data['time'], historical_data['net_sent'], 'm-', label='Enviado')
line_net_recv, = ax_net.plot(historical_data['time'], historical_data['net_recv'], 'c-', label='Recibido')
ax_net.set_title("Tráfico de Red (Bytes/s)", fontsize=10); ax_net.set_xlabel("Tiempo (segundos)", fontsize=8); ax_net.set_ylabel("Bytes/s", fontsize=8); ax_net.set_ylim(0, 500000); ax_net.set_xlim(1, MAX_SAMPLES); ax_net.legend(loc='upper left', fontsize=8); ax_net.grid(True)
fig_net.tight_layout(pad=1.5)
# Devuelve todos los elementos que se necesitan para la actualización
return {
'fig_usage': fig_usage,
'fig_net': fig_net,
'lines': {
'cpu': line_cpu, 'mem': line_mem, 'disk': line_disk,
'net_sent': line_net_sent, 'net_recv': line_net_recv
},
'ax_net': ax_net # Para auto-escalado
}
def update_monitor(root, lines, ax_net, mpl_canvas_usage, mpl_canvas_net, label_load, label_threads):
"""
Obtiene los datos de psutil y actualiza todos los gráficos.
Esta función debe ser llamada por root.after()
"""
global LAST_NET_COUNTERS
# 1. Obtener los nuevos datos del sistema
cpu_percent = psutil.cpu_percent(interval=None)
mem_percent = psutil.virtual_memory().percent
disk_percent = psutil.disk_usage('/').percent
load_avg = os.getloadavg() if hasattr(os, 'getloadavg') else (0.0, 0.0, 0.0)
thread_count = CURRENT_PROCESS.num_threads()
# 2. Calcular el Tráfico de Red (Bytes/s)
current_net_counters = psutil.net_io_counters()
bytes_sent_rate = (current_net_counters.bytes_sent - LAST_NET_COUNTERS.bytes_sent) / 1.0
bytes_recv_rate = (current_net_counters.bytes_recv - LAST_NET_COUNTERS.bytes_recv) / 1.0
LAST_NET_COUNTERS = current_net_counters
# 3. Actualizar los Labels
label_load.config(text=f"Carga (1m/5m/15m): {load_avg[0]:.2f} / {load_avg[1]:.2f} / {load_avg[2]:.2f}")
label_threads.config(text=f"Hilos del Proceso: {thread_count}")
# 4. Actualizar datos históricos
historical_data['cpu'].pop(0); historical_data['cpu'].append(cpu_percent)
historical_data['memory'].pop(0); historical_data['memory'].append(mem_percent)
historical_data['disk'].pop(0); historical_data['disk'].append(disk_percent)
historical_data['net_sent'].pop(0); historical_data['net_sent'].append(bytes_sent_rate)
historical_data['net_recv'].pop(0); historical_data['net_recv'].append(bytes_recv_rate)
# 5. Actualizar las líneas de los gráficos
lines['cpu'].set_ydata(historical_data['cpu'])
lines['mem'].set_ydata(historical_data['memory'])
lines['disk'].set_ydata(historical_data['disk'])
lines['net_sent'].set_ydata(historical_data['net_sent'])
lines['net_recv'].set_ydata(historical_data['net_recv'])
# Auto-escalado de red
max_net = max(max(historical_data['net_sent']), max(historical_data['net_recv']))
if max_net * 1.1 > ax_net.get_ylim()[1]:
ax_net.set_ylim(0, max_net * 1.1)
# 6. Redibujar los canvases
mpl_canvas_usage.draw_idle()
mpl_canvas_net.draw_idle()
# 7. Llamada recursiva
# Importante: se llama a sí misma en el hilo principal de Tkinter
root.after(1000, update_monitor, root, lines, ax_net, mpl_canvas_usage, mpl_canvas_net, label_load, label_threads)