# src/logger.py # Structured logging configuration. import logging import logging.config import os def setup_logging(): logs_dir = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "logs", ) os.makedirs(logs_dir, exist_ok=True) LOG_FORMAT = "%(asctime)s | %(name)-8s | %(levelname)-7s | %(message)s" DATE_FORMAT = "%Y-%m-%d %H:%M:%S" logging_config = { "version": 1, "disable_existing_loggers": False, "formatters": { "standard": { "format": LOG_FORMAT, "datefmt": DATE_FORMAT, }, }, "handlers": { "console": { "class": "logging.StreamHandler", "level": "INFO", "formatter": "standard", # Use stderr so stdout can stay clean for JSON in CLI mode. "stream": "ext://sys.stderr", }, "file_boot": { "class": "logging.handlers.RotatingFileHandler", "level": "INFO", "formatter": "standard", "filename": os.path.join(logs_dir, "boot.log"), "maxBytes": 10_485_760, "backupCount": 3, "encoding": "utf8", }, "file_api": { "class": "logging.handlers.RotatingFileHandler", "level": "INFO", "formatter": "standard", "filename": os.path.join(logs_dir, "api.log"), "maxBytes": 10_485_760, "backupCount": 3, "encoding": "utf8", }, "file_pipeline": { "class": "logging.handlers.RotatingFileHandler", "level": "INFO", "formatter": "standard", "filename": os.path.join(logs_dir, "pipeline.log"), "maxBytes": 10_485_760, "backupCount": 3, "encoding": "utf8", }, }, "loggers": { "boot": { "level": "INFO", "handlers": ["console", "file_boot"], "propagate": False, }, "api": { "level": "INFO", "handlers": ["console", "file_api"], "propagate": False, }, "pipeline": { "level": "INFO", "handlers": ["console", "file_pipeline"], "propagate": False, }, }, "root": { "level": "INFO", "handlers": ["console"], }, } logging.config.dictConfig(logging_config)