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
/in/
/out/
/logs/
# Python
__pycache__/

View file

@ -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.

View file

@ -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

View file

@ -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" \

View file

@ -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