agent_m/agentm/utils/logger.py
mscrnt 5179d425fc Add initial project structure and core functionality for Agent M
- Created .gitignore to exclude virtual environment, logs, and database files.
- Updated README.md with project description, features, folder structure, requirements, and usage instructions.
- Implemented versioning and developer ID in agentm/__init__.py.
- Developed main application logic in agentm/app.py, including credential handling and screen navigation.
- Added database initialization and ROM management logic in agentm/logic/db.py and agentm/logic/db_functions.py.
- Integrated DIAMBRA login functionality in agentm/logic/diambra_login.py.
- Created ROM verification and caching system in agentm/logic/roms.py.
- Designed user interface components for home and login screens in agentm/views/home.py and agentm/views/login.py.
- Added logging utility in agentm/utils/logger.py for better debugging and tracking.
- Included assets such as game images, styles, and logos.
- Updated requirements.txt with necessary dependencies for the project.
2025-05-20 23:20:29 -07:00

82 lines
2.7 KiB
Python

import os
import logging
import inspect
from logging.handlers import RotatingFileHandler
from rich.logging import RichHandler
DEFAULT_UNIFIED_LOGFILE = "logs/agentm.log"
DEFAULT_LOG_LEVEL = os.environ.get("AGENTM_LOG_LEVEL", "DEBUG")
def get_logger(name="AGENTM", level=None, max_bytes=5 * 1024 * 1024, backup_count=5):
logger = logging.getLogger(name)
if logger.handlers:
return logger # Already configured
level = level or DEFAULT_LOG_LEVEL
if isinstance(level, str):
level = getattr(logging, level.upper(), logging.INFO)
logger.setLevel(level)
# 🎛 Rich Console Handler
console_handler = RichHandler(
rich_tracebacks=True,
markup=True,
show_time=True,
show_level=True,
show_path=False,
)
logger.addHandler(console_handler)
# 🛡 Unified File Logger
log_dir = os.getenv("AGENTM_LOG_DIR", "logs")
try:
os.makedirs(log_dir, exist_ok=True)
unified_path = os.path.join(log_dir, "agentm.log")
file_handler = RotatingFileHandler(unified_path, maxBytes=max_bytes, backupCount=backup_count, encoding="utf-8")
file_formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s", "%Y-%m-%d %H:%M:%S")
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
except Exception:
logger.warning("⚠️ File logging disabled: could not create log directory or file.")
return logger
def get_module_logger(level=None):
module_name = inspect.stack()[1].frame.f_globals.get("__name__", "unknown")
return get_logger(name="AGENTM", level=level) # Use unified logger name
def log_with_caller(level: str, message: str):
stack = inspect.stack()
callee = stack[1]
callee_func = callee.function
callee_module = callee.frame.f_globals.get("__name__", "unknown")
caller_func = "unknown"
caller_module = "unknown"
for frame in stack[2:]:
if frame.function not in {"wrapper", "inner", "<lambda>"}:
caller_func = frame.function
caller_module = frame.frame.f_globals.get("__name__", "unknown")
break
logger = get_logger("AGENTM")
full_message = (
f"{message}{callee_module}.{callee_func} "
f"→ called by {caller_module}.{caller_func}"
)
getattr(logger, level.lower())(full_message)
def set_global_log_level(level: str):
resolved_level = getattr(logging, level.upper(), logging.INFO)
logging.getLogger().setLevel(resolved_level)
for name in logging.root.manager.loggerDict:
logging.getLogger(name).setLevel(resolved_level)
log_with_caller("info", f"🔧 Global log level set to {level.upper()}")