import functools import logging import logging.config from typing import Any # Global logger instance used throughout the app log = logging.getLogger('root') def get_logger(name: str): """Returns a logger instance by name.""" return logging.getLogger(name) def setup_logging(settings: Any): """ Configures logging based on provided settings. Moving this here prevents immediate execution on module import. """ log_file_path = getattr(settings, 'LOG_PATH', {}).get('app', '/logs/aether_api.log') try: logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': False, # Critical to not kill FastAPI/Uvicorn loggers 'formatters': { 'default': {'format': '[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s'}, 'long': {'format': '[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S'}, 'short': {'format': '[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s', 'datefmt': '%H:%M:%S'}, }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'stream': 'ext://sys.stderr', 'formatter': 'short', }, 'log_file_all': { 'level': 'NOTSET', 'class': 'logging.handlers.RotatingFileHandler', 'formatter': 'long', 'filename': log_file_path, 'maxBytes': 10485760, # 10 MB 'backupCount': 9 }, }, 'loggers': { 'uvicorn': {'handlers': ['console'], 'level': 'INFO'}, }, 'root': { 'handlers': ['log_file_all'], 'level': 'WARNING', } }) log.info(f"Logging successfully configured. Path: {log_file_path}") except Exception as e: print(f"Error configuring logging: {e}") logging.basicConfig(level=logging.WARNING) def logger_reset(func): """ Decorator to log function entry/exit and reset log levels. """ @functools.wraps(func) def wrapper(*args, **kwargs): # Local safer access to root logger root_log = logging.getLogger('root') if func.__name__ not in ['redis_lookup_id_random', 'sql_enable_part', 'sql_hidden_part']: root_log.info(f'*** Function: "{func.__name__}()"') root_log.debug(f'*** Function Positional Args: {args}\nFunction Key Args: {kwargs}') init_log_level = root_log.level returned_result = func(*args, **kwargs) # Reset level in case it was changed during func execution root_log.setLevel(init_log_level) return returned_result return wrapper