import logging import sys import os from logging.handlers import RotatingFileHandler from pythonjsonlogger import jsonlogger """ Structured Logger Service Production-ready logger with JSON formatting, file rotation, and log levels """ class Logger: def __init__(self): self.log_level = os.getenv('LOG_LEVEL', 'INFO').upper() self.log_format = os.getenv('LOG_FORMAT', 'json') # 'json' or 'text' self.log_dir = os.getenv('LOG_DIR', './logs') # Ensure log directory exists os.makedirs(self.log_dir, exist_ok=True) # Create logger self.logger = logging.getLogger('test_project') self.logger.setLevel(getattr(logging, self.log_level, logging.INFO)) # Remove existing handlers self.logger.handlers = [] # Add handlers self._setup_handlers() def _setup_handlers(self): """Setup log handlers""" # Console handler (always enabled) console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(getattr(logging, self.log_level, logging.INFO)) if self.log_format == 'json': formatter = jsonlogger.JsonFormatter( '%(timestamp)s %(level)s %(name)s %(message)s', timestamp=True ) else: formatter = logging.Formatter( '%(asctime)s [%(levelname)s] %(name)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) console_handler.setFormatter(formatter) self.logger.addHandler(console_handler) # File handlers (only in production or if LOG_TO_FILE is enabled) if os.getenv('ENVIRONMENT') == 'production' or os.getenv('LOG_TO_FILE', 'false').lower() == 'true': # Combined log file combined_handler = RotatingFileHandler( filename=os.path.join(self.log_dir, 'combined.log'), maxBytes=10 * 1024 * 1024, # 10MB backupCount=5 ) combined_handler.setLevel(logging.DEBUG) combined_handler.setFormatter(formatter) self.logger.addHandler(combined_handler) # Error log file error_handler = RotatingFileHandler( filename=os.path.join(self.log_dir, 'error.log'), maxBytes=10 * 1024 * 1024, # 10MB backupCount=5 ) error_handler.setLevel(logging.ERROR) error_handler.setFormatter(formatter) self.logger.addHandler(error_handler) def info(self, message: str, extra: dict = None): """Log info message""" self.logger.info(message, extra=extra or {}) def error(self, message: str, extra: dict = None): """Log error message""" self.logger.error(message, extra=extra or {}) def warning(self, message: str, extra: dict = None): """Log warning message""" self.logger.warning(message, extra=extra or {}) def debug(self, message: str, extra: dict = None): """Log debug message""" self.logger.debug(message, extra=extra or {}) def critical(self, message: str, extra: dict = None): """Log critical message""" self.logger.critical(message, extra=extra or {}) # Singleton instance logger = Logger()