From 3c40720a95fd68f5218da8fa9956a6072ab18138 Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Fri, 13 Feb 2026 16:41:27 +0000 Subject: [PATCH] Now set up full Django logging for 404 --- core/views/expo.py | 10 +++++-- settings.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/core/views/expo.py b/core/views/expo.py index a496aa347..84367f7bd 100644 --- a/core/views/expo.py +++ b/core/views/expo.py @@ -1,3 +1,4 @@ +import logging import os import re from datetime import datetime @@ -294,6 +295,7 @@ def expopage(request, path): """Either renders an HTML page from expoweb with all the menus, or serves an unadorned binary file with mime type """ + logger = logging.getLogger('troggle') # print(" - EXPOPAGES delivering the file: '{}':{} as MIME type: {}".format(request.path, path,getmimetype(path)),flush=True) if path.startswith("noinfo") and settings.PUBLIC_SITE and not request.user.is_authenticated: @@ -342,11 +344,15 @@ def expopage(request, path): return HttpResponse(content=content, content_type=content_type) except FileNotFoundError as e: message = f" ! - 404 FileNotFound REMOTE_ADDR: {meta['REMOTE_ADDR']:>15} [{stamp}] '/{path}'" - DataIssue.objects.create(parser="view404", message=message) + #DataIssue.objects.create(parser="view404", message=message) + logmsg = f"[{meta['REMOTE_ADDR']:>15}] '/{path}' FILE NOT FOUND 404" + logger.warning(logmsg) return render(request, "pagenotfound.html", {"path": path}, status=404) except Exception as e: message = f" ! - 404? REMOTE_ADDR: {meta['REMOTE_ADDR']:>15} [{stamp}] '/{path}' {e}" - DataIssue.objects.create(parser="view404", message=message) + #DataIssue.objects.create(parser="view404", message=message) + logmsg = f"[{meta['REMOTE_ADDR']:>15}] '/{path}' FILE NOT FOUND 404" + logger.warning(logmsg) return render(request, "pagenotfound.html", {"path": path}, status=404) diff --git a/settings.py b/settings.py index d8ec54be5..d1d3e282b 100644 --- a/settings.py +++ b/settings.py @@ -1,5 +1,7 @@ +import logging import sys from datetime import date +from pathlib import Path from socket import gethostname """ @@ -76,6 +78,76 @@ USE_L10N = True FIX_PERMISSIONS = [] + +### LOGGING set up here -------------------- +class RequireDevServerTrue(logging.Filter): + """Filter that only allows records through if DEVSERVER is True.""" + def filter(self, record): + return DEVSERVER + +PRIMARY_LOG_DIR = Path("/var/log/troggle") +FALLBACK_LOG_DIR = Path(__file__).parent / "BACKUP_LOGGING" +log_filename = "troggle.log" + +try: + PRIMARY_LOG_DIR.mkdir(parents=True, exist_ok=True) + final_log_path = PRIMARY_LOG_DIR / log_filename +except (PermissionError, OSError): + FALLBACK_LOG_DIR.mkdir(parents=True, exist_ok=True) + final_log_path = FALLBACK_LOG_DIR / log_filename + print(f"!! Log permission denied at /var/log. Falling back to: {final_log_path}") + +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "timestamped": { + "format": "{asctime} {message}", + # "format": "{levelname} {asctime} {module} {message}", + # "format": "{levelname} [{module}:{lineno}] {message}" # for bug reporting + "style": "{", + "datefmt": "%Y-%m-%d %H:%M:%S", # No milliseconds + }, + "simple": { + "format": "{levelname} {asctime} [{module}:{lineno}] {message}", + "style": "{", + "datefmt": "%Y-%m-%d %H:%M:%S", # No milliseconds + }, + }, + "filters": { + "require_devserver_true": { + # Use the full import path to your class + # If this is in settings.py, you can use 'settings.RequireDevServerTrue' + "()": "settings.RequireDevServerTrue", + }, + }, + "handlers": { + "file": { + "level": "WARNING", + "class": "logging.handlers.RotatingFileHandler", + "filename": final_log_path, + "maxBytes": 1024 * 1024 * 5, + "backupCount": 5, + "formatter": "timestamped", + }, + "console": { + "level": "INFO", + "filters": ["require_devserver_true"], # Applied here! + "class": "logging.StreamHandler", + "formatter": "simple", + }, + }, + "loggers": { + "troggle": { + "handlers": ["file", "console"], + "level": "INFO", + "propagate": True, + }, + }, +} +### LOGGING set up end -------------------- + + # top-level survex file basename (without .svx) # SURVEX_TOPNAME = "1623-and-1626-no-schoenberg-hs" SURVEX_TOPNAME = "troggle_import_root" # same, but without all the 'essentials' gubbins