Source code for mailos.utils.logger_utils
"""Logging utilities."""
import inspect
import logging
import os
from logging.handlers import RotatingFileHandler
# Create logs directory if it doesn't exist
if not os.path.exists("logs"):
os.makedirs("logs")
# Global flag to track if root logger has been configured
_root_configured = False
# Cache for module loggers
_loggers = {}
def _configure_root_logger(log_level=logging.INFO):
"""Configure root logger if not already configured."""
global _root_configured
if _root_configured:
return
root_logger = logging.getLogger()
for handler in root_logger.handlers[:]:
root_logger.removeHandler(handler)
# Set the root logger level
root_logger.setLevel(log_level)
# Create handlers
file_handler = RotatingFileHandler(
"logs/mailos.log", maxBytes=1024 * 1024, backupCount=5 # 1MB
)
console_handler = logging.StreamHandler()
# Set log levels for handlers
file_handler.setLevel(log_level)
console_handler.setLevel(log_level)
# Create formatters and add it to handlers
file_format = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
file_handler.setFormatter(file_format)
console_handler.setFormatter(file_format)
# Add handlers to root logger
root_logger.addHandler(file_handler)
root_logger.addHandler(console_handler)
_root_configured = True
# Configure root logger at import time
_configure_root_logger()
class LazyLogger:
"""A proxy that creates the logger only when needed."""
def __init__(self):
self._logger = None
def __get_logger(self):
if self._logger is None:
# Get the caller's module name
frame = inspect.currentframe()
while frame:
if frame.f_globals["__name__"] != __name__:
module_name = frame.f_globals["__name__"]
break
frame = frame.f_back
# Create and cache logger
if module_name not in _loggers:
_loggers[module_name] = logging.getLogger(module_name)
_loggers[module_name].propagate = True
_loggers[module_name].handlers = []
self._logger = _loggers[module_name]
return self._logger
def __getattr__(self, name):
return getattr(self.__get_logger(), name)
# Create a single instance to be imported
logger = LazyLogger()
# For backward compatibility
[docs]
def setup_logger(name, log_level=logging.INFO):
"""Set up logger for a given name (deprecated)."""
if name not in _loggers:
_loggers[name] = logging.getLogger(name)
_loggers[name].propagate = True
_loggers[name].handlers = []
return _loggers[name]
# Export only what's needed
__all__ = ["logger"]