diff --git a/.gitignore b/.gitignore index 99e3b92..ae9c5fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Staging data — not code /in/ /out/ +/logs/ # Python __pycache__/ diff --git a/README.md b/README.md index 7e1474b..1bf2948 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,8 @@ Browser vm-bench LXC Proxmox Host (srv2) │ └── requirements.txt ├── open-api.yaml # API spec (single source of truth) ├── in/ # Shared staging directory (gitignored) -└── out/ # Shared output directory (gitignored) +├── out/ # Shared output directory (gitignored) +├── logs/ # Shared log files (gitignored) ``` ## Features @@ -287,5 +288,21 @@ large virtual disk, but only a fraction is used. progress. Replace with real `qm create`, `qm importdisk`, and `qm set` commands when deploying to the Proxmox host. -**Staging files**: `/mnt/converter/in/` and `/mnt/converter/out/` are gitignored — -they contain user data, not code. +**Staging files**: `/mnt/converter/in/`, `/mnt/converter/out/`, and `/mnt/converter/logs/` are gitignored — +they contain runtime data, not code. + +## Logging + +Both services write to two locations simultaneously: + +| Destination | How to access | +|-------------|---------------| +| **File** (shared) | `tail -f /mnt/converter/logs/vm-bench.log` (frontend) or `vm-bench-backend.log` (backend) | +| **Journal** (per-service) | `journalctl -u vm-bench -f` (frontend) or `journalctl -u vm-bench-backend -f` (backend) | + +Log files rotate automatically at 10 MB, keeping 5 historical files +(e.g. `vm-bench.log`, `vm-bench.log.1`, `vm-bench.log.2`, …). + +The file logs are the authoritative source — they're written to the shared +`/mnt/converter/logs/` directory, accessible from both the Proxmox host and +the LXC container. diff --git a/backend/app.py b/backend/app.py index 61817c2..3ccbb56 100644 --- a/backend/app.py +++ b/backend/app.py @@ -9,6 +9,9 @@ Matches open-api.yaml v1.1.0 spec exactly. from __future__ import annotations import logging +from logging.handlers import RotatingFileHandler +from pathlib import Path + from fastapi import FastAPI, HTTPException, Request from fastapi.middleware.cors import CORSMiddleware @@ -28,11 +31,24 @@ from provisioner import submit_job, get_job_status, cleanup_staging # --------------------------------------------------------------------------- # Logging # --------------------------------------------------------------------------- -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s %(levelname)s %(message)s", -) logger = logging.getLogger("backend") +logger.setLevel(logging.INFO) + +# Console → systemd journal +_ch = logging.StreamHandler() +_ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) +logger.addHandler(_ch) + +# File handler → shared log directory +LOG_DIR = Path("/mnt/converter/logs") +LOG_DIR.mkdir(parents=True, exist_ok=True) +_fh = RotatingFileHandler( + LOG_DIR / "vm-bench-backend.log", maxBytes=10 * 1024 * 1024, backupCount=5, +) +_fh.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s")) +logger.addHandler(_fh) + +logger.info("Backend starting — log file: %s", LOG_DIR / "vm-bench-backend.log") # --------------------------------------------------------------------------- # Constants diff --git a/backend/install.sh b/backend/install.sh index d8b7bdc..3d5e895 100755 --- a/backend/install.sh +++ b/backend/install.sh @@ -60,6 +60,7 @@ for d in \ "$CONVERTER_ROOT" \ "$CONVERTER_ROOT/in" \ "$CONVERTER_ROOT/out" \ + "$CONVERTER_ROOT/logs" \ "$CONVERTER_ROOT/backend" \ "$CONVERTER_ROOT/frontend" \ "$CONVERTER_ROOT/frontend/templates" \ diff --git a/frontend/app.py b/frontend/app.py index e8ed12f..2923335 100644 --- a/frontend/app.py +++ b/frontend/app.py @@ -16,6 +16,7 @@ Routes: from __future__ import annotations import logging +from logging.handlers import RotatingFileHandler import os import shutil import subprocess @@ -48,7 +49,23 @@ STAGING = Path("/mnt/converter/in") api = ApiClient() logger = logging.getLogger("vm-bench") -logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") +logger.setLevel(logging.INFO) + +# Console handler → systemd journal via stdout +_ch = logging.StreamHandler() +_ch.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) +logger.addHandler(_ch) + +# File handler → shared log directory on /mnt/converter +LOG_DIR = Path("/mnt/converter/logs") +LOG_DIR.mkdir(parents=True, exist_ok=True) +_fh = RotatingFileHandler( + LOG_DIR / "vm-bench.log", maxBytes=10 * 1024 * 1024, backupCount=5, +) +_fh.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s")) +logger.addHandler(_fh) + +logger.info("Frontend starting — log file: %s", LOG_DIR / "vm-bench.log") # Config VM_ID_MIN = 21000