Files
vacuum-wall/daemon/handlers/logs.py
T
mteehan 2f215793e9 docs: add docstrings to all API endpoints and daemon handlers
Add comprehensive docstrings to firewall, DHCP, proxy, wireguard, certs,
and logs API endpoints. Document parameters, return values, and error cases
for the documentation system.
2026-05-30 16:15:45 +00:00

95 lines
2.8 KiB
Python

"""Logs daemon handler.
Reads system logs and journal entries.
"""
import logging
from pathlib import Path
from daemon.server import registry
from lib.common import run_proc
logger = logging.getLogger(__name__)
PROJECT_DIR = Path(__file__).resolve().parent.parent.parent
_APP_LOG_FILE = PROJECT_DIR / "data" / "logs" / "vacuum-wall.log"
_MAX_LINES = 200
def _tail_file(path: str, n: int = _MAX_LINES, sudo: bool = False) -> str:
"""Return the last N lines of a file, optionally via sudo.
Args:
path: Absolute path to the file to read.
n: Number of trailing lines to return.
sudo: Whether to use sudo to access the file.
Returns:
Truncated file content or an error message string.
"""
try:
if sudo:
result = run_proc(["cat", path], sudo=True)
lines = result.stdout.splitlines(keepends=True)
else:
with open(path) as f:
lines = f.readlines()
return "".join(lines[-n:])
except FileNotFoundError:
return "(log file not found)\n"
except PermissionError:
return "(permission denied)\n"
def _sudo_journalctl(unit: str, n: int = _MAX_LINES) -> str:
"""Return recent journalctl output for a systemd unit via sudo.
Args:
unit: Systemd unit name to query.
n: Number of journal lines to return.
Returns:
Journal output or an error message string.
"""
try:
result = run_proc(
["journalctl", "--unit=" + unit, "-n", str(n)],
sudo=True,
check=False,
timeout=10,
)
output = result.stdout.strip()
return output if output else f"(no journal entries for {unit})\n"
except Exception as exc:
return f"(error reading journal: {exc})\n"
@registry.register("GET", "/logs/journal")
def journal(_request, _body) -> str:
"""GET /logs/journal — return vacuum-wall daemon journal entries."""
return _sudo_journalctl("vacuum-wall")
@registry.register("GET", "/logs/nginx/access")
def nginx_access(_request, _body) -> str:
"""GET /logs/nginx/access — return recent nginx access log lines."""
return _tail_file("/var/log/nginx/access.log", sudo=True)
@registry.register("GET", "/logs/nginx/error")
def nginx_error(_request, _body) -> str:
"""GET /logs/nginx/error — return recent nginx error log lines."""
return _tail_file("/var/log/nginx/error.log", sudo=True)
@registry.register("GET", "/logs/dnsmasq")
def dnsmasq_log(_request, _body) -> str:
"""GET /logs/dnsmasq — return recent dnsmasq journal entries."""
return _sudo_journalctl("dnsmasq")
@registry.register("GET", "/logs/app")
def app_log(_request, _body) -> str:
"""GET /logs/app — return recent application log lines."""
return _tail_file(str(_APP_LOG_FILE))