--- a +++ b/src/utils/logger_config.py @@ -0,0 +1,74 @@ +import logging +import sys +from datetime import datetime +from pathlib import Path +from pythonjsonlogger import jsonlogger + + +def setup_logger(name: str = __name__) -> logging.Logger: + """Configure and return a JSON logger with custom formatting""" + # Create logs directory if it doesn't exist + log_dir = Path("logs") + log_dir.mkdir(exist_ok=True) + + # Create logger + logger = logging.getLogger(name) + logger.setLevel(logging.INFO) + + # Remove existing handlers to avoid duplicates + logger.handlers = [] + + # Custom JSON formatter + class CustomJsonFormatter(jsonlogger.JsonFormatter): + def add_fields(self, log_record, record, message_dict): + super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict) + + # Add timestamp + if not log_record.get('timestamp'): + log_record['timestamp'] = datetime.utcnow().isoformat() + + # Add log level + if log_record.get('level'): + log_record['level'] = log_record['level'].upper() + else: + log_record['level'] = record.levelname + + # Add module info + log_record['module'] = record.module + log_record['function'] = record.funcName + log_record['line'] = record.lineno + + # Create formatters + json_formatter = CustomJsonFormatter( + '%(timestamp)s %(level)s %(name)s %(module)s %(function)s %(line)s %(message)s' + ) + + # Console handler (JSON format) + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setFormatter(json_formatter) + logger.addHandler(console_handler) + + # File handler (JSON format) + file_handler = logging.FileHandler( + log_dir / f"{datetime.now().strftime('%Y-%m-%d')}_application.log" + ) + file_handler.setFormatter(json_formatter) + logger.addHandler(file_handler) + + return logger + + +# Example usage +if __name__ == "__main__": + # Test the logger + logger = setup_logger("test_logger") + + # Log some test messages + logger.info("Info message", extra={"user": "test_user", "action": "login"}) + logger.warning("Warning message", extra={"user": "test_user", "status": "retry"}) + logger.error("Error message", extra={"user": "test_user", "error_code": 500}) + + try: + raise ValueError("Test exception") + except Exception as e: + logger.exception("Exception occurred", extra={"error_type": type(e).__name__})