# 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