radio/web/api/logs.py
profit 3d635b742c Initial commit: self-hosted personal radio station
Flask + React web UI with audio player, podcast queue, feed management,
episode browser, music library, schedule viewer, and log tail.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 19:01:33 -07:00

49 lines
1.3 KiB
Python

"""GET /api/logs — tail log files."""
import os
from flask import Blueprint, jsonify, request
from ..config import LOG_DIR
bp = Blueprint("logs", __name__)
ALLOWED_LOGS = {"poller", "liquidsoap", "icecast_access", "icecast_error"}
@bp.route("/logs")
def get_logs():
log_name = request.args.get("file", "poller")
lines_count = request.args.get("lines", 50, type=int)
lines_count = min(lines_count, 500)
if log_name not in ALLOWED_LOGS:
return jsonify({"error": f"Unknown log file. Allowed: {ALLOWED_LOGS}"}), 400
log_path = LOG_DIR / f"{log_name}.log"
if not log_path.exists():
return jsonify({"lines": [], "file": log_name, "exists": False})
# Read last N lines efficiently
try:
with open(log_path, "rb") as f:
f.seek(0, os.SEEK_END)
size = f.tell()
# Read up to 1MB from the end
read_size = min(size, 1024 * 1024)
f.seek(max(0, size - read_size))
content = f.read().decode("utf-8", errors="replace")
all_lines = content.splitlines()
tail = all_lines[-lines_count:]
except Exception as e:
return jsonify({"error": str(e)}), 500
return jsonify({
"lines": tail,
"file": log_name,
"exists": True,
"total_lines": len(all_lines),
})