""" Logging configuration for thrillwiki project. This module provides a base logging configuration that can be extended by environment-specific settings. It supports both console and file logging with optional JSON formatting for production. Why python-decouple? - Already used in base.py for consistency - Simpler API than django-environ - Sufficient for our configuration needs - Better separation of config from code Log Levels (in order of severity): - DEBUG: Detailed diagnostic information - INFO: Confirmation that things are working as expected - WARNING: Indication of potential problems - ERROR: Serious problems that prevented function execution - CRITICAL: Critical errors that may cause application failure """ from pathlib import Path from decouple import config # ============================================================================= # Log File Configuration # ============================================================================= # Base directory for log files - defaults to logs/ in the backend directory LOG_DIR = Path(config("LOG_DIR", default="logs")) # Ensure log directory exists (will be created if not) LOG_DIR.mkdir(parents=True, exist_ok=True) # ============================================================================= # Log Formatters # ============================================================================= LOGGING_FORMATTERS = { # Verbose format for development - human readable with full context "verbose": { "format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}", "style": "{", }, # JSON format for production - machine parseable for log aggregation "json": { "()": "pythonjsonlogger.jsonlogger.JsonFormatter", "format": ( "%(levelname)s %(asctime)s %(module)s %(process)d " "%(thread)d %(message)s" ), }, # Simple format for console output "simple": { "format": "{levelname} {message}", "style": "{", }, # Request logging format "request": { "format": "{levelname} {asctime} [{request_id}] {message}", "style": "{", }, } # ============================================================================= # Log Handlers # ============================================================================= LOGGING_HANDLERS = { # Console handler - for development and container environments "console": { "class": "logging.StreamHandler", "formatter": "verbose", "level": config("CONSOLE_LOG_LEVEL", default="INFO"), }, # Main application log file "file": { "class": "logging.handlers.RotatingFileHandler", "filename": str(LOG_DIR / "thrillwiki.log"), "maxBytes": 1024 * 1024 * 10, # 10MB "backupCount": 5, "formatter": config("FILE_LOG_FORMATTER", default="json"), "level": config("FILE_LOG_LEVEL", default="INFO"), }, # Error-only log file for quick error identification "error_file": { "class": "logging.handlers.RotatingFileHandler", "filename": str(LOG_DIR / "errors.log"), "maxBytes": 1024 * 1024 * 15, # 15MB "backupCount": 10, "formatter": "json", "level": "ERROR", }, # Performance log file for slow queries and performance issues "performance": { "class": "logging.handlers.RotatingFileHandler", "filename": str(LOG_DIR / "performance.log"), "maxBytes": 1024 * 1024 * 10, # 10MB "backupCount": 5, "formatter": "json", "level": "INFO", }, # Security event log file "security": { "class": "logging.handlers.RotatingFileHandler", "filename": str(LOG_DIR / "security.log"), "maxBytes": 1024 * 1024 * 10, # 10MB "backupCount": 10, "formatter": "json", "level": "INFO", }, } # ============================================================================= # Logger Configuration # ============================================================================= LOGGING_LOGGERS = { # Django framework logging "django": { "handlers": ["console", "file"], "level": config("DJANGO_LOG_LEVEL", default="WARNING"), "propagate": False, }, # Django database queries - useful for debugging N+1 issues "django.db.backends": { "handlers": ["console"], "level": config("DB_LOG_LEVEL", default="WARNING"), "propagate": False, }, # Django request handling "django.request": { "handlers": ["console", "error_file"], "level": "ERROR", "propagate": False, }, # Django security events "django.security": { "handlers": ["console", "security"], "level": "WARNING", "propagate": False, }, # Application logging "thrillwiki": { "handlers": ["console", "file"], "level": config("APP_LOG_LEVEL", default="INFO"), "propagate": False, }, # Performance monitoring "performance": { "handlers": ["performance"], "level": config("PERFORMANCE_LOG_LEVEL", default="INFO"), "propagate": False, }, # Query optimization warnings "query_optimization": { "handlers": ["console", "file"], "level": config("QUERY_LOG_LEVEL", default="WARNING"), "propagate": False, }, # N+1 query detection "nplusone": { "handlers": ["console"], "level": config("NPLUSONE_LOG_LEVEL", default="WARNING"), "propagate": False, }, # Request logging "request_logging": { "handlers": ["console"], "level": config("REQUEST_LOG_LEVEL", default="INFO"), "propagate": False, }, # Security events "security": { "handlers": ["console", "security"], "level": "INFO", "propagate": False, }, # Celery task logging "celery": { "handlers": ["console", "file"], "level": config("CELERY_LOG_LEVEL", default="INFO"), "propagate": False, }, } # ============================================================================= # Complete Logging Configuration # ============================================================================= LOGGING = { "version": 1, "disable_existing_loggers": False, "formatters": LOGGING_FORMATTERS, "handlers": LOGGING_HANDLERS, "root": { "level": config("ROOT_LOG_LEVEL", default="INFO"), "handlers": ["console"], }, "loggers": LOGGING_LOGGERS, }