add monitor beta
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
from .amd_server import AMDMonitorServer, get_amd_server
|
||||
|
||||
__all__ = ["AMDMonitorServer", "get_amd_server"]
|
||||
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
AMD Monitor Server
|
||||
==================
|
||||
WebSocket server for streaming AMD GPU stats to frontend
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
from typing import Set
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AMDMonitorServer:
|
||||
def __init__(self):
|
||||
self.monitor = None # Lazy load
|
||||
self.clients: Set = set()
|
||||
self.running = False
|
||||
self.update_interval = 1.0 # seconds
|
||||
|
||||
def _get_monitor(self):
|
||||
"""Lazy load monitor to avoid import issues at startup"""
|
||||
if self.monitor is None:
|
||||
from ..utils.amd_utils import get_amd_monitor
|
||||
self.monitor = get_amd_monitor()
|
||||
return self.monitor
|
||||
|
||||
async def broadcast(self, message: str):
|
||||
"""Send data to all connected clients"""
|
||||
if self.clients:
|
||||
await asyncio.gather(
|
||||
*[client.send_str(message) for client in self.clients],
|
||||
return_exceptions=True
|
||||
)
|
||||
|
||||
async def handle_client(self, ws):
|
||||
"""Handle WebSocket client connection"""
|
||||
self.clients.add(ws)
|
||||
logger.info(f"AMD Monitor: Client connected. Total clients: {len(self.clients)}")
|
||||
|
||||
try:
|
||||
async for msg in ws:
|
||||
if msg.type == 1: # Text message
|
||||
if msg.data == "ping":
|
||||
await ws.send_str("pong")
|
||||
except Exception as e:
|
||||
logger.error(f"AMD Monitor: Client error: {e}")
|
||||
finally:
|
||||
self.clients.discard(ws)
|
||||
logger.info(f"AMD Monitor: Client disconnected. Total clients: {len(self.clients)}")
|
||||
|
||||
async def stream_data(self):
|
||||
"""Stream GPU stats periodically"""
|
||||
monitor = self._get_monitor()
|
||||
|
||||
while self.running:
|
||||
try:
|
||||
if monitor.available:
|
||||
stats = monitor.get_gpu_stats(0) # GPU 0
|
||||
|
||||
data = {
|
||||
"type": "amd_stats",
|
||||
"gpu_id": stats.gpu_id,
|
||||
"gpu_utilization": stats.utilization_gpu,
|
||||
"vram_usage_pct": stats.utilization_memory,
|
||||
"vram_used_mb": stats.memory_used / (1024 * 1024),
|
||||
"vram_total_mb": stats.memory_total / (1024 * 1024),
|
||||
"temperature": stats.temperature,
|
||||
"fan_speed": stats.fan_speed,
|
||||
"is_available": stats.is_available,
|
||||
"method": monitor.method,
|
||||
"gpu_count": monitor.gpu_count
|
||||
}
|
||||
else:
|
||||
data = {
|
||||
"type": "amd_stats",
|
||||
"is_available": False,
|
||||
"error": "AMD backend not available",
|
||||
"method": None,
|
||||
"gpu_count": 0
|
||||
}
|
||||
|
||||
await self.broadcast(json.dumps(data))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"AMD Monitor: Stream error: {e}")
|
||||
|
||||
await asyncio.sleep(self.update_interval)
|
||||
|
||||
def start(self, loop=None):
|
||||
"""Start the monitoring loop safely"""
|
||||
if self.running:
|
||||
return
|
||||
|
||||
self.running = True
|
||||
logger.info("AMD Monitor: Starting data stream")
|
||||
|
||||
|
||||
# Singleton instance
|
||||
_amd_server = None
|
||||
|
||||
def get_amd_server() -> AMDMonitorServer:
|
||||
global _amd_server
|
||||
if _amd_server is None:
|
||||
_amd_server = AMDMonitorServer()
|
||||
return _amd_server
|
||||
Reference in New Issue
Block a user