2f215793e9
Add comprehensive docstrings to firewall, DHCP, proxy, wireguard, certs, and logs API endpoints. Document parameters, return values, and error cases for the documentation system.
95 lines
2.8 KiB
Python
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))
|