Source code for base.log_config
import logging
import os
from typing import Dict, Any
import colorlog
import yaml
CONFIG_FILEPATH = os.path.join(os.path.dirname(__file__), "../../config.yaml")
# Global formatting for all loggers
log_colors = {
"DEBUG": "cyan",
"INFO": "green",
"WARNING": "yellow",
"ERROR": "red",
"CRITICAL": "red,bg_white",
}
# Formatter for INFO and WARNING levels
simple_formatter = colorlog.ColoredFormatter(
fmt="%(log_color)s[%(asctime)s, %(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
log_colors=log_colors,
)
# Formatter for DEBUG, ERROR, and CRITICAL levels
detailed_formatter = colorlog.ColoredFormatter(
fmt="%(log_color)s%(asctime)s [%(levelname)s] %(message)s\n ⤷ In %(module)s:%(lineno)d, %(funcName)s",
datefmt="%Y-%m-%d %H:%M:%S",
log_colors=log_colors,
)
[docs]
class CustomHandler(logging.StreamHandler):
"""Custom logging handler that applies different formatting based on log level
Provides level-specific message formatting where INFO and WARNING messages
use a simplified format, while DEBUG, ERROR, and CRITICAL messages include
detailed context information such as module name, line number, and function name.
"""
[docs]
def load_config() -> Dict[str, Any]:
"""Load the application configuration from the YAML configuration file.
Returns:
Dict[str, Any]: Parsed configuration data as a dictionary.
Raises:
FileNotFoundError: If the configuration file cannot be found at the expected path.
yaml.YAMLError: If the configuration file contains invalid YAML syntax.
"""
try:
with open(CONFIG_FILEPATH, "r") as file:
return yaml.safe_load(file)
except FileNotFoundError:
raise
[docs]
def get_logger(module_name: str = "base") -> logging.Logger:
"""Create or retrieve a configured logger for a specific module.
Sets up a logger with custom formatting and debug level configuration
based on the module-specific settings in config.yaml. If no module-specific
configuration exists, falls back to the base module settings.
Args:
module_name (str): Name of the module to create a logger for.
Must match a module defined in config.yaml ``logging.modules``.
Default: "base".
Returns:
logging.Logger: Configured logger instance for the specified module.
Raises:
FileNotFoundError: If the configuration file cannot be loaded.
KeyError: If the configuration structure is invalid.
"""
config = load_config()
logger = logging.getLogger(module_name)
if logger.hasHandlers():
logger.handlers.clear()
handler = CustomHandler()
logger.addHandler(handler)
# Default to base debug setting
debug_enabled = config["logging"]["base"]["debug"]
# Override with module-specific setting if it exists
if module_name in config["logging"]["modules"]:
debug_enabled = config["logging"]["modules"][module_name]["debug"]
logger.setLevel(logging.DEBUG if debug_enabled else logging.INFO)
return logger