Files
B42/at_django_boilerplate/core/logging/views.py
2026-01-07 12:09:20 +05:30

129 lines
3.0 KiB
Python
Executable File

# utils/log_viewer.py
from pathlib import Path
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.http import Http404
from django.shortcuts import render
from datetime import datetime
from django.utils import timezone
def tail(filepath, lines=500, chunk_size=1024):
with open(filepath, "rb") as f:
f.seek(0, 2)
file_size = f.tell()
buffer = b""
pointer = file_size
while pointer > 0 and buffer.count(b"\n") < lines:
read_size = min(chunk_size, pointer)
pointer -= read_size
f.seek(pointer)
buffer = f.read(read_size) + buffer
return buffer.decode(errors="ignore").splitlines()[-lines:]
@staff_member_required
def log_list(request):
log_dir = Path(settings.BASE_DIR) / "logs"
files = []
for f in log_dir.glob("*.log"):
stat = f.stat()
files.append({
"name": f.name,
"size": stat.st_size,
"mtime": timezone.make_aware(
datetime.fromtimestamp(stat.st_mtime))
})
return render(request, "logging/logs_list.html", {"files": files})
# @staff_member_required
# def log_detail(request, filename):
# log_dir = Path(settings.LOG_VIEWER_DIR)
# file_path = log_dir / filename
# if not file_path.exists():
# raise Http404
# lines = tail(file_path, settings.LOG_VIEWER_MAX_LINES)
# return render(
# request,
# "logging/log_detail.html",
# {"filename": filename, "lines": lines},
# )
import re
from pathlib import Path
from django.conf import settings
from django.shortcuts import render
from django.http import Http404
LOG_PATTERN = re.compile(
r"""
^\[
(?P<time>[\d\-:\s,]+)
\]\s+\[
(?P<level>DEBUG|INFO|WARNING|ERROR|CRITICAL)
\]\s+
(?P<logger>[^:]+):
\s+
(?P<message>.*)
$
""",
re.VERBOSE,
)
LEVEL_ORDER = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
def log_detail(request, filename):
log_dir = Path(settings.LOG_VIEWER_DIR)
file_path = log_dir / filename
if not file_path.exists() or not file_path.is_file():
raise Http404("Log file not found")
lines = []
with file_path.open("r", errors="replace") as f:
for raw in f:
raw = raw.rstrip("\n")
match = LOG_PATTERN.match(raw)
if match:
data = match.groupdict()
data["raw"] = raw
data["is_trace"] = False
else:
# stack trace / continuation line
data = {
"time": "",
"level": "",
"logger": "",
"message": raw,
"raw": raw,
"is_trace": True,
}
lines.append(data)
return render(
request,
"logging/log_detail.html",
{
"filename": filename,
"lines": lines,
},
)