From 8c8e1be0dbc02df5277fbeef2373f4da1d525404 Mon Sep 17 00:00:00 2001 From: nessi Date: Fri, 21 Aug 2026 21:12:27 +0200 Subject: [PATCH] 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. --- app.py | 17 ++++++++++++++++- docker-compose.yml | 4 ++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app.py b/app.py index 0969c80..b6d6e86 100644 --- a/app.py +++ b/app.py @@ -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): diff --git a/docker-compose.yml b/docker-compose.yml index 5d81c53..ce6150f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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