Repository: ephios-dev/ephios

Issue:
Proper logging setup
We should provide proper logging configuration in `settings.py`. See https://docs.djangoproject.com/en/3.1/topics/logging/#configuring-logging


Discussion:
This also includes the AdminEmailHandler as it is currently not invoked, so we are not notified about errors
The AdminEmailHandler is currently working fine, meaning we are notified about all ERROR messages. We could enable logging of INFO or WARNING messages to the console and let uWSGI log them to its logfile (as in https://stackoverflow.com/questions/46747036/which-django-python-handler-class-will-pass-logs-to-the-uwsgi-logger). Currently there isn't really a need for that.

Resolving patch:
diff --git a/ephios/core/apps.py b/ephios/core/apps.py
--- a/ephios/core/apps.py
+++ b/ephios/core/apps.py
@@ -1,6 +1,11 @@
+import logging
+
 from django.apps import AppConfig
+from django.conf import settings
 from dynamic_preferences.registries import preference_models
 
+logger = logging.getLogger(__name__)
+
 
 class CoreAppConfig(AppConfig):
     name = "ephios.core"
@@ -12,3 +17,5 @@ def ready(self):
 
         EventTypePreference = self.get_model("EventTypePreference")
         preference_models.register(EventTypePreference, event_type_preference_registry)
+
+        logger.info("Installed plugins: %s", ", ".join(settings.PLUGINS))
diff --git a/ephios/core/plugins.py b/ephios/core/plugins.py
--- a/ephios/core/plugins.py
+++ b/ephios/core/plugins.py
@@ -11,8 +11,6 @@
 
 # The plugin mechanics are heavily inspired by pretix (then licenced under Apache 2.0) - Check it out!
 
-logger.info("Installed plugins: %s", ", ".join(settings.PLUGINS))
-
 
 def get_all_plugins():
     """
diff --git a/ephios/settings.py b/ephios/settings.py
--- a/ephios/settings.py
+++ b/ephios/settings.py
@@ -1,4 +1,5 @@
 import copy
+import datetime
 import os
 from datetime import timedelta
 from email.utils import getaddresses
@@ -212,11 +213,16 @@
 ADMINS = getaddresses([env("ADMINS")])
 
 # logging
+LOGGING_FILE = env.str("LOGGING_FILE", default=None)
+use_file_logging = not DEBUG and LOGGING_FILE is not None
+if use_file_logging:
+    Path(LOGGING_FILE).parent.mkdir(parents=True, exist_ok=True)
+
 LOGGING = {
     "version": 1,
     "disable_existing_loggers": False,
     "formatters": {
-        "default": {"format": "%(levelname)s %(asctime)s %(name)s %(module)s %(message)s"},
+        "default": {"format": "[%(levelname)s] %(asctime)s %(name)s :: %(message)s"},
     },
     "filters": {
         "require_debug_false": {
@@ -227,26 +233,57 @@
         },
     },
     "handlers": {
+        "console": {
+            "level": "DEBUG",
+            "class": "logging.StreamHandler",
+            "formatter": "default",
+            "filters": ["require_debug_true"],
+        },
         "mail_admins": {
             "level": "ERROR",
             "filters": ["require_debug_false"],
             "class": "django.utils.log.AdminEmailHandler",
         },
-        "console": {
-            "level": "INFO",
-            "class": "logging.StreamHandler",
+        "file": {
+            "level": "DEBUG",
             "formatter": "default",
+            "filters": ["require_debug_false"],
+            **(
+                {
+                    "class": "logging.handlers.TimedRotatingFileHandler",
+                    "filename": LOGGING_FILE,
+                    "when": "midnight",
+                    "backupCount": env.int("LOGGING_BACKUP_DAYS", default=14),
+                    "atTime": datetime.time(4),
+                    "encoding": "utf-8",
+                }
+                if use_file_logging
+                else {
+                    "class": "logging.NullHandler",
+                }
+            ),
         },
     },
     "loggers": {
+        "ephios": {
+            "handlers": ["mail_admins", "console", "file"],
+            "level": "DEBUG" if DEBUG else "INFO",
+            "propagate": False,
+        },
         "django": {
-            "handlers": ["mail_admins", "console"],
+            "handlers": [],
             "level": "INFO",
-            "propagate": False,
+            "propagate": True,
+        },
+        "django.server": {
+            "handlers": [],
+            "level": "INFO",
+            "propagate": True,
         },
     },
     "root": {
-        "handlers": ["mail_admins", "console"],
+        "handlers": ["mail_admins", "console", "file"],
+        "level": "INFO",
     },
 }
 


Test patch: