feat: shared file-based logging to /mnt/converter/logs/

Both frontend and backend now write rotating log files to
/mnt/converter/logs/ (shared between host and LXC):

  /mnt/converter/logs/vm-bench.log          (frontend)
  /mnt/converter/logs/vm-bench-backend.log   (backend)

- RotatingFileHandler: 10 MB per file, 5 backups
- Console handler still writes to systemd journal
- Logs/ directory is gitignored and auto-created on startup
- Install script creates logs/ directory
This commit is contained in:
Claus Lohmar 2026-07-21 18:52:58 +00:00
parent 42d3cdf1fe
commit 0e7f8c81f3
5 changed files with 60 additions and 8 deletions

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
# Staging data — not code # Staging data — not code
/in/ /in/
/out/ /out/
/logs/
# Python # Python
__pycache__/ __pycache__/

View file

@ -48,7 +48,8 @@ Browser vm-bench LXC Proxmox Host (srv2)
│ └── requirements.txt │ └── requirements.txt
├── open-api.yaml # API spec (single source of truth) ├── open-api.yaml # API spec (single source of truth)
├── in/ # Shared staging directory (gitignored) ├── in/ # Shared staging directory (gitignored)
└── out/ # Shared output directory (gitignored) ├── out/ # Shared output directory (gitignored)
├── logs/ # Shared log files (gitignored)
``` ```
## Features ## 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 progress. Replace with real `qm create`, `qm importdisk`, and `qm set` commands
when deploying to the Proxmox host. when deploying to the Proxmox host.
**Staging files**: `/mnt/converter/in/` and `/mnt/converter/out/` are gitignored — **Staging files**: `/mnt/converter/in/`, `/mnt/converter/out/`, and `/mnt/converter/logs/` are gitignored —
they contain user data, not code. 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.

View file

@ -9,6 +9,9 @@ Matches open-api.yaml v1.1.0 spec exactly.
from __future__ import annotations from __future__ import annotations
import logging import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path
from fastapi import FastAPI, HTTPException, Request from fastapi import FastAPI, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
@ -28,11 +31,24 @@ from provisioner import submit_job, get_job_status, cleanup_staging
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Logging # Logging
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
logger = logging.getLogger("backend") 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 # Constants

View file

@ -60,6 +60,7 @@ for d in \
"$CONVERTER_ROOT" \ "$CONVERTER_ROOT" \
"$CONVERTER_ROOT/in" \ "$CONVERTER_ROOT/in" \
"$CONVERTER_ROOT/out" \ "$CONVERTER_ROOT/out" \
"$CONVERTER_ROOT/logs" \
"$CONVERTER_ROOT/backend" \ "$CONVERTER_ROOT/backend" \
"$CONVERTER_ROOT/frontend" \ "$CONVERTER_ROOT/frontend" \
"$CONVERTER_ROOT/frontend/templates" \ "$CONVERTER_ROOT/frontend/templates" \

View file

@ -16,6 +16,7 @@ Routes:
from __future__ import annotations from __future__ import annotations
import logging import logging
from logging.handlers import RotatingFileHandler
import os import os
import shutil import shutil
import subprocess import subprocess
@ -48,7 +49,23 @@ STAGING = Path("/mnt/converter/in")
api = ApiClient() api = ApiClient()
logger = logging.getLogger("vm-bench") 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 # Config
VM_ID_MIN = 21000 VM_ID_MIN = 21000