import logging import sys import json from logging.handlers import RotatingFileHandler import os from datetime import datetime # 1. Ensure logs directory exists LOG_DIR = "logs" os.makedirs(LOG_DIR, exist_ok=True) # 2. Custom JSON Formatter class JsonFormatter(logging.Formatter): def format(self, record): log_record = { "timestamp": datetime.utcfromtimestamp(record.created).isoformat(), "level": record.levelname, "message": record.getMessage(), "module": record.module, "function": record.funcName, "line": record.lineno, "path": record.pathname } # Add extra fields if available if hasattr(record, "request_id"): log_record["request_id"] = record.request_id if record.exc_info: log_record["exception"] = self.formatException(record.exc_info) return json.dumps(log_record, ensure_ascii=False) # 3. Setup Logger Function def setup_logging(): logger = logging.getLogger("waiting_system") logger.setLevel(logging.DEBUG) # Remove existing handlers to avoid duplicates logger.handlers = [] # Handler 1: Console (Human Readable) console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging.INFO) console_format = logging.Formatter( '%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s' ) console_handler.setFormatter(console_format) logger.addHandler(console_handler) # Handler 2: File (JSON Structured for Analysis) file_handler = RotatingFileHandler( os.path.join(LOG_DIR, "system.json.log"), maxBytes=10*1024*1024, # 10MB backupCount=5, encoding='utf-8' ) file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(JsonFormatter()) logger.addHandler(file_handler) # Handler 3: Human Readable File (Legacy/Easy Read) text_handler = RotatingFileHandler( os.path.join(LOG_DIR, "system.log"), maxBytes=10*1024*1024, # 10MB backupCount=5, encoding='utf-8' ) text_handler.setLevel(logging.INFO) text_handler.setFormatter(console_format) logger.addHandler(text_handler) return logger # Singleton Logger Instance logger = setup_logging()