117 lines
5.4 KiB
Python
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) |