feat: add GPU status logging with state tracking to prevent duplicate log messages and configure NVIDIA runtime in docker-compose

Add graphics_log_state global to track GPU query status and prevent duplicate log messages. Log warning with error_summary() when nvidia-smi is unavailable or returns non-zero exit code. Log info message when GPU status becomes available with GPU count and binary path. Track signature tuples for unavailable/failed/ok states including GPU index/name/temperature/utilization.
This commit is contained in:
2026-08-21 21:12:27 +02:00
parent 7d1987c4f4
commit 8c8e1be0db
2 changed files with 20 additions and 1 deletions
+16 -1
View File
@@ -87,6 +87,7 @@ datastore_refresh_lock = threading.Lock()
raid_refresh_lock = threading.Lock()
datastore_cache = {"stored_at": 0.0, "snapshot": None, "raid": None, "raid_at": 0.0}
raid_log_state = None
graphics_log_state = None
hardware_log_once = set()
LANG_NAMES = {"de":"Deutsch", "deu":"Deutsch", "ger":"Deutsch", "en":"Englisch", "eng":"Englisch", "ja":"Japanisch", "jpn":"Japanisch", "ko":"Koreanisch", "kor":"Koreanisch", "fr":"Französisch", "fra":"Französisch", "fre":"Französisch", "es":"Spanisch", "spa":"Spanisch", "it":"Italienisch", "ita":"Italienisch", "ru":"Russisch", "rus":"Russisch", "zh":"Chinesisch", "zho":"Chinesisch", "chi":"Chinesisch", "und":"Unbekannt", "":"Unbekannt"}
@@ -356,12 +357,22 @@ def io_pressure():
def graphics_snapshot():
"""Read NVIDIA GPU details with short, non-blocking subprocess timeouts."""
global graphics_log_state
query = "index,name,uuid,serial,pci.bus_id,driver_version,pstate,temperature.gpu,utilization.gpu,utilization.memory,memory.total,memory.used,memory.free,power.draw,power.limit,fan.speed,clocks.current.graphics,clocks.current.memory,clocks.max.graphics,clocks.max.memory,compute_mode"
try:
result = subprocess.run([NVIDIA_SMI_BIN, f"--query-gpu={query}", "--format=csv,noheader,nounits"], capture_output=True, text=True, timeout=5, check=False)
except (OSError, subprocess.SubprocessError):
except (OSError, subprocess.SubprocessError) as exc:
signature = ("unavailable", str(exc))
if signature != graphics_log_state:
log.warning("GPU-Abfrage fehlgeschlagen: %s (%s)", NVIDIA_SMI_BIN, error_summary(exc))
graphics_log_state = signature
return {"available": False, "gpus": [], "processes": [], "error": "NVIDIA SMI nicht verfügbar"}
if result.returncode != 0 or not result.stdout.strip():
detail = " ".join((result.stderr or result.stdout or "keine Ausgabe").split())[:240]
signature = ("failed", result.returncode, detail)
if signature != graphics_log_state:
log.warning("GPU-Abfrage fehlgeschlagen: %s (Code %s): %s", NVIDIA_SMI_BIN, result.returncode, detail)
graphics_log_state = signature
return {"available": False, "gpus": [], "processes": [], "error": "Keine NVIDIA-GPU erkannt"}
fields = query.split(",")
gpus = []
@@ -386,6 +397,10 @@ def graphics_snapshot():
processes.append({"pid": values[0], "name": values[1], "memory": values[2]})
except (OSError, subprocess.SubprocessError):
pass
signature = ("ok", tuple((gpu.get("index"), gpu.get("name"), gpu.get("temperature.gpu"), gpu.get("utilization.gpu")) for gpu in gpus))
if signature != graphics_log_state:
log.info("GPU-Status verfügbar: %s NVIDIA-GPU(s) via %s", len(gpus), NVIDIA_SMI_BIN)
graphics_log_state = signature
return {"available": bool(gpus), "gpus": gpus, "processes": processes, "error": None if gpus else "Keine NVIDIA-GPU erkannt", "updated_at": time.time()}
def smart_status(device):
+4
View File
@@ -3,6 +3,7 @@ services:
build: .
container_name: media-max
restart: unless-stopped
gpus: all
ports:
- "8099:8099"
devices:
@@ -16,6 +17,9 @@ services:
- "host.docker.internal:host-gateway"
env_file:
- .env
environment:
NVIDIA_VISIBLE_DEVICES: ${NVIDIA_VISIBLE_DEVICES:-all}
NVIDIA_DRIVER_CAPABILITIES: ${NVIDIA_DRIVER_CAPABILITIES:-compute,utility}
volumes:
# Host-Pfad deiner Film-Library -> interner Dashboard-Pfad
- ${FILM_MEDIA_VOLUME}:/media/filme:ro