import os import logging from logging.handlers import RotatingFileHandler from flask import request, session, has_request_context class RequestContextFilter(logging.Filter): """Adds request information to every log record.""" def filter(self, record): if has_request_context(): record.user = session.get("user_name", "Anonymous") record.ip = request.remote_addr or "Unknown" record.method = request.method record.url = request.url else: record.user = "System" record.ip = "-" record.method = "-" record.url = "-" return True class LoggerService: LOG_DIR = "logs" APP_LOG = "app.log" ERROR_LOG = "error.log" DEBUG_LOG = "debug.log" MAX_BYTES = 10 * 1024 * 1024 # 10 MB BACKUP_COUNT = 10 @classmethod def init_app(cls, app): os.makedirs(cls.LOG_DIR, exist_ok=True) formatter = logging.Formatter( fmt=( "%(asctime)s | " "%(levelname)-8s | " "User=%(user)s | " "IP=%(ip)s | " "%(method)s | " "%(url)s | " "%(message)s" ), datefmt="%Y-%m-%d %H:%M:%S" ) context_filter = RequestContextFilter() # Remove default handlers app.logger.handlers.clear() # ========================== # Application Log # ========================== app_handler = RotatingFileHandler( os.path.join(cls.LOG_DIR, cls.APP_LOG), maxBytes=cls.MAX_BYTES, backupCount=cls.BACKUP_COUNT, encoding="utf-8" ) app_handler.setLevel(logging.INFO) app_handler.setFormatter(formatter) app_handler.addFilter(context_filter) # ========================== # Error Log # ========================== error_handler = RotatingFileHandler( os.path.join(cls.LOG_DIR, cls.ERROR_LOG), maxBytes=cls.MAX_BYTES, backupCount=cls.BACKUP_COUNT, encoding="utf-8" ) error_handler.setLevel(logging.ERROR) error_handler.setFormatter(formatter) error_handler.addFilter(context_filter) # ========================== # Debug Log # ========================== debug_handler = RotatingFileHandler( os.path.join(cls.LOG_DIR, cls.DEBUG_LOG), maxBytes=cls.MAX_BYTES, backupCount=cls.BACKUP_COUNT, encoding="utf-8" ) debug_handler.setLevel(logging.DEBUG) debug_handler.setFormatter(formatter) debug_handler.addFilter(context_filter) # ========================== # Console Log # ========================== console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) console_handler.setFormatter(formatter) console_handler.addFilter(context_filter) # ========================== # Logger Configuration # ========================== app.logger.setLevel(logging.DEBUG) app.logger.addHandler(app_handler) app.logger.addHandler(error_handler) app.logger.addHandler(debug_handler) app.logger.addHandler(console_handler) # ========================== # Automatic Request Logging # ========================== @app.before_request def before_request(): app.logger.info("Request Started") @app.after_request def after_request(response): app.logger.info( f"Request Completed | Status={response.status_code}" ) return response # ========================== # Exception Logging # ========================== @app.errorhandler(Exception) def log_exception(error): app.logger.exception( f"Unhandled Exception: {str(error)}" ) raise error app.logger.info("=" * 70) app.logger.info("Application Started Successfully") app.logger.info("=" * 70)