refactor(node): Streamline resource monitoring logic

This commit is contained in:
Vito Sansevero
2025-11-28 09:50:14 -08:00
parent 5c0110936f
commit f600c60b2a
+12 -162
View File
@@ -8,29 +8,23 @@ import time
from typing import Dict, Any, Tuple
from ...base import ComfyAssetsBaseNode
from .logic import ResourceMonitor, validate_update_interval, format_memory_size, format_percentage, get_global_monitor
from .logic import get_global_monitor
class ResourceMonitorNode(ComfyAssetsBaseNode):
"""
ComfyUI node for real-time resource monitoring
Displays GPU utilization, VRAM usage, CPU usage, and RAM usage
with real-time updates at 1-second intervals.
Displays GPU utilization, VRAM usage, CPU usage, RAM usage, and temperature
with real-time updates at 1-second intervals via WebSocket.
Inputs:
- display_mode (STRING): Output format ("text", "json", "both")
- enable_gpu (BOOLEAN): Enable GPU monitoring
- enable_system (BOOLEAN): Enable system monitoring
Provides a visual interface with live charts and per-node performance tracking.
Outputs:
- stats (STRING): Formatted statistics output
- json_data (STRING): JSON statistics for chaining
- stats (STRING): Empty string (all display handled by UI widget)
- json_data (STRING): JSON statistics for chaining with other nodes
"""
# Class variable to maintain monitor instance across executions
_monitor_instance: ResourceMonitor = None
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
@@ -40,31 +34,8 @@ class ResourceMonitorNode(ComfyAssetsBaseNode):
Dict with required and optional input specifications
"""
return {
"required": {
"display_mode": (
["text", "json", "both"],
{
"default": "text",
"tooltip": "Output format for monitoring data"
},
),
},
"optional": {
"enable_gpu": (
"BOOLEAN",
{
"default": True,
"tooltip": "Enable GPU monitoring (requires NVIDIA GPU and drivers)"
},
),
"enable_system": (
"BOOLEAN",
{
"default": True,
"tooltip": "Enable system resource monitoring (CPU, RAM)"
},
),
},
"required": {},
"optional": {},
}
RETURN_TYPES = ("STRING", "STRING")
@@ -73,32 +44,14 @@ class ResourceMonitorNode(ComfyAssetsBaseNode):
def monitor_resources(
self,
display_mode: str,
enable_gpu: bool = True,
enable_system: bool = True,
) -> Tuple[str, str]:
"""
Monitor system and GPU resources with real-time updates
Args:
display_mode: Output format ("text", "json", "both")
enable_gpu: Whether to monitor GPU resources
enable_system: Whether to monitor system resources
Returns:
Tuple of (formatted_stats, json_data)
Raises:
ValueError: If validation fails
"""
try:
# Validate inputs
self.validate_inputs(
display_mode=display_mode,
enable_gpu=enable_gpu,
enable_system=enable_system
)
# Get the global continuous monitor (starts automatically)
continuous_monitor = get_global_monitor()
@@ -114,121 +67,18 @@ class ResourceMonitorNode(ComfyAssetsBaseNode):
}
stats_dict = waiting_stats
# Filter based on enabled monitoring
if not enable_gpu:
stats_dict["gpu"]["available"] = False
if not enable_system:
stats_dict["system"]["available"] = False
# Return JSON data for the UI widget
json_data = json.dumps(stats_dict, indent=2)
# Format output based on display mode
if display_mode == "text":
formatted_stats = self._format_text_output(stats_dict, enable_gpu, enable_system)
json_data = ""
elif display_mode == "json":
formatted_stats = ""
json_data = json.dumps(stats_dict, indent=2)
else: # "both"
formatted_stats = self._format_text_output(stats_dict, enable_gpu, enable_system)
json_data = json.dumps(stats_dict, indent=2)
# Log monitoring status
self.log_info(
f"Continuous Monitoring Active: GPU={enable_gpu}, System={enable_system}, "
f"Display={display_mode} (Real-time updates via WebSocket)"
)
return formatted_stats, json_data
# Return empty string for stats (UI displays everything)
return "", json_data
except Exception as e:
error_msg = f"Failed to monitor resources: {str(e)}"
self.handle_error(error_msg, e)
def _format_text_output(
self,
stats_dict: Dict[str, Any],
enable_gpu: bool,
enable_system: bool
) -> str:
"""
Format statistics as human-readable text
Args:
stats_dict: Statistics dictionary
enable_gpu: Whether GPU monitoring is enabled
enable_system: Whether system monitoring is enabled
Returns:
Formatted text string
"""
lines = []
lines.append("=== ComfyUI Resource Monitor ===")
# GPU Statistics
if enable_gpu:
gpu = stats_dict["gpu"]
if gpu["available"]:
lines.append("\n🖥️ GPU Statistics:")
lines.append(f" Utilization: {gpu['utilization']}%")
lines.append(f" VRAM: {format_memory_size(gpu['memory_used'])} / "
f"{format_memory_size(gpu['memory_total'])} "
f"({format_percentage(gpu['memory_percent'])})")
lines.append(f" Temperature: {gpu['temperature']}°C")
lines.append(f" Power: {gpu['power_draw']}W")
else:
lines.append("\n🖥️ GPU: Not Available")
lines.append(" (Requires NVIDIA GPU and drivers)")
# System Statistics
if enable_system:
system = stats_dict["system"]
if system["available"]:
lines.append("\n💻 System Statistics:")
lines.append(f" CPU Usage: {format_percentage(system['cpu_percent'])}")
lines.append(f" RAM: {format_memory_size(system['ram_used'])} / "
f"{format_memory_size(system['ram_total'])} "
f"({format_percentage(system['ram_percent'])})")
else:
lines.append("\n💻 System: Not Available")
lines.append(" (Requires psutil library)")
# Add timestamp
import time
timestamp = time.strftime("%H:%M:%S", time.localtime(stats_dict["timestamp"]))
lines.append(f"\n⏰ Last Updated: {timestamp}")
return "\n".join(lines)
def validate_inputs(
self,
display_mode: str,
enable_gpu: bool,
enable_system: bool,
) -> None:
"""
Validate inputs specific to resource monitor
Args:
display_mode: Display mode to validate
enable_gpu: GPU monitoring flag
enable_system: System monitoring flag
Raises:
ValueError: If validation fails
"""
# Validate display mode
valid_modes = ["text", "json", "both"]
if display_mode not in valid_modes:
raise ValueError(f"Invalid display_mode '{display_mode}'. Must be one of: {valid_modes}")
# Validate boolean flags
for flag_name, flag_value in [("enable_gpu", enable_gpu), ("enable_system", enable_system)]:
if not isinstance(flag_value, bool):
raise ValueError(f"{flag_name} must be a boolean, got {type(flag_value).__name__}")
# Check that at least one monitoring type is enabled
if not enable_gpu and not enable_system:
raise ValueError("At least one monitoring type (GPU or System) must be enabled")
# Node class mappings for ComfyUI registration