2026-02-26 17:08:49 +05:30
|
|
|
import os
|
|
|
|
|
import logging
|
|
|
|
|
from logging.handlers import RotatingFileHandler
|
2026-03-17 15:35:52 +05:30
|
|
|
from flask import request, session, has_request_context
|
2026-02-26 17:08:49 +05:30
|
|
|
|
|
|
|
|
|
2026-03-17 15:35:52 +05:30
|
|
|
class RequestContextFilter(logging.Filter):
|
2026-07-30 14:38:37 +05:30
|
|
|
"""Adds request information to every log record."""
|
2026-02-26 17:08:49 +05:30
|
|
|
|
2026-03-17 15:35:52 +05:30
|
|
|
def filter(self, record):
|
|
|
|
|
|
|
|
|
|
if has_request_context():
|
2026-07-30 14:38:37 +05:30
|
|
|
record.user = session.get("user_name", "Anonymous")
|
|
|
|
|
record.ip = request.remote_addr or "Unknown"
|
2026-03-17 15:35:52 +05:30
|
|
|
record.method = request.method
|
|
|
|
|
record.url = request.url
|
|
|
|
|
else:
|
|
|
|
|
record.user = "System"
|
2026-07-30 14:38:37 +05:30
|
|
|
record.ip = "-"
|
|
|
|
|
record.method = "-"
|
|
|
|
|
record.url = "-"
|
2026-03-17 15:35:52 +05:30
|
|
|
|
|
|
|
|
return True
|
2026-02-26 17:08:49 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
class LoggerService:
|
|
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
LOG_DIR = "logs"
|
2026-02-26 17:08:49 +05:30
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
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)
|
2026-02-26 17:08:49 +05:30
|
|
|
|
2026-03-17 15:35:52 +05:30
|
|
|
formatter = logging.Formatter(
|
2026-07-30 14:38:37 +05:30
|
|
|
fmt=(
|
|
|
|
|
"%(asctime)s | "
|
|
|
|
|
"%(levelname)-8s | "
|
|
|
|
|
"User=%(user)s | "
|
|
|
|
|
"IP=%(ip)s | "
|
|
|
|
|
"%(method)s | "
|
|
|
|
|
"%(url)s | "
|
|
|
|
|
"%(message)s"
|
|
|
|
|
),
|
|
|
|
|
datefmt="%Y-%m-%d %H:%M:%S"
|
2026-02-26 17:08:49 +05:30
|
|
|
)
|
|
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
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"
|
2026-02-26 17:08:49 +05:30
|
|
|
)
|
|
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
app_handler.setLevel(logging.INFO)
|
|
|
|
|
app_handler.setFormatter(formatter)
|
|
|
|
|
app_handler.addFilter(context_filter)
|
|
|
|
|
|
|
|
|
|
# ==========================
|
|
|
|
|
# Error Log
|
|
|
|
|
# ==========================
|
2026-02-26 17:08:49 +05:30
|
|
|
error_handler = RotatingFileHandler(
|
2026-07-30 14:38:37 +05:30
|
|
|
os.path.join(cls.LOG_DIR, cls.ERROR_LOG),
|
|
|
|
|
maxBytes=cls.MAX_BYTES,
|
|
|
|
|
backupCount=cls.BACKUP_COUNT,
|
|
|
|
|
encoding="utf-8"
|
2026-02-26 17:08:49 +05:30
|
|
|
)
|
2026-07-30 14:38:37 +05:30
|
|
|
|
2026-02-26 17:08:49 +05:30
|
|
|
error_handler.setLevel(logging.ERROR)
|
|
|
|
|
error_handler.setFormatter(formatter)
|
2026-07-30 14:38:37 +05:30
|
|
|
error_handler.addFilter(context_filter)
|
2026-02-26 17:08:49 +05:30
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
# ==========================
|
|
|
|
|
# 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"
|
|
|
|
|
)
|
2026-02-26 17:08:49 +05:30
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
debug_handler.setLevel(logging.DEBUG)
|
|
|
|
|
debug_handler.setFormatter(formatter)
|
|
|
|
|
debug_handler.addFilter(context_filter)
|
2026-03-17 15:35:52 +05:30
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
# ==========================
|
|
|
|
|
# Console Log
|
|
|
|
|
# ==========================
|
|
|
|
|
console_handler = logging.StreamHandler()
|
|
|
|
|
|
|
|
|
|
console_handler.setLevel(logging.INFO)
|
|
|
|
|
console_handler.setFormatter(formatter)
|
2026-03-17 15:35:52 +05:30
|
|
|
console_handler.addFilter(context_filter)
|
|
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
# ==========================
|
|
|
|
|
# Logger Configuration
|
|
|
|
|
# ==========================
|
2026-02-26 17:08:49 +05:30
|
|
|
app.logger.setLevel(logging.DEBUG)
|
2026-03-17 15:35:52 +05:30
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
app.logger.addHandler(app_handler)
|
2026-02-26 17:08:49 +05:30
|
|
|
app.logger.addHandler(error_handler)
|
2026-07-30 14:38:37 +05:30
|
|
|
app.logger.addHandler(debug_handler)
|
2026-02-26 17:08:49 +05:30
|
|
|
app.logger.addHandler(console_handler)
|
|
|
|
|
|
2026-07-30 14:38:37 +05:30
|
|
|
# ==========================
|
|
|
|
|
# Automatic Request Logging
|
|
|
|
|
# ==========================
|
2026-02-26 17:08:49 +05:30
|
|
|
@app.before_request
|
2026-07-30 14:38:37 +05:30
|
|
|
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)
|