import logging import logging.handlers import os from typing import TYPE_CHECKING, Optional from .adapter import ExtraFormatter, MergedLoggerAdapter from .discord import DiscordLogHandler if TYPE_CHECKING: from core.config import CoreConfig __all__ = ( "init_root_logger", "create_logger", ) core_cfg: Optional["CoreConfig"] = None artemis_logger = logging.getLogger("artemis") log_fmt_str = "[%(asctime)s] %(title)s | %(levelname)s | %(message)s" log_fmt = ExtraFormatter(log_fmt_str) def init_root_logger(cfg: "CoreConfig"): global core_cfg core_cfg = cfg if not os.path.exists(cfg.logging.log_dir): os.mkdir(cfg.logging.log_dir) if not os.access(cfg.logging.log_dir, os.W_OK): print( f"Log directory {cfg.logging.log_dir} NOT writable, please check permissions" ) exit(1) console_handler = logging.StreamHandler() console_handler.setFormatter(log_fmt) artemis_logger.addHandler(console_handler) if cfg.logging.discord_webhook: artemis_logger.addHandler(DiscordLogHandler(cfg.logging.discord_webhook, cfg.logging.discord_who_to_ping)) def create_logger( title: str, level: Optional["logging._Level"] = None, *, logger_name: Optional[str] = None, ): logger_name = logger_name or title.lower().replace(" ", "_") logger = artemis_logger.getChild(logger_name) if getattr(logger, "initialized", False): logger = MergedLoggerAdapter(logger, {"title": title}) logger.setLevel(level or logging.INFO) return logger if core_cfg is None: raise RuntimeError("Root logger has not been initialized.") file_handler = logging.handlers.TimedRotatingFileHandler( os.path.join(core_cfg.logging.log_dir, f"{logger_name}.log"), when="d", backupCount=10, ) file_handler.setFormatter(log_fmt) logger.addHandler(file_handler) logger.setLevel(level or logging.INFO) logger.initialized = True return MergedLoggerAdapter(logger, {"title": title})