master_adapt_detect/logging_config.py
2025-10-01 14:32:55 -05:00

128 lines
No EOL
4.4 KiB
Python

#!/usr/bin/env python3
"""
Logging Configuration - Dual output to terminal and file for crash tracking
"""
import logging
import sys
import os
from datetime import datetime
def setup_dual_logging(log_level=logging.INFO):
"""
Configure logging to output to both terminal and file
Args:
log_level: Logging level (default: logging.INFO)
Returns:
logger: Configured logger instance
"""
# Create logger
logger = logging.getLogger('master_adapt_detect')
logger.setLevel(log_level)
# Prevent duplicate handlers if called multiple times
if logger.handlers:
return logger
# Create formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Console handler (terminal output)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(log_level)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# File handler (file output)
log_filename = f"master_adapt_detect_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
file_handler = logging.FileHandler(log_filename, mode='w')
file_handler.setLevel(log_level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Log the setup
logger.info(f"Dual logging initialized - Console: {log_level}, File: {log_filename}")
return logger
def log_system_info(logger):
"""Log system information for debugging"""
import platform
import psutil
logger.info("="*60)
logger.info("SYSTEM INFORMATION")
logger.info("="*60)
logger.info(f"Platform: {platform.platform()}")
logger.info(f"Python version: {platform.python_version()}")
logger.info(f"CPU count: {psutil.cpu_count()}")
logger.info(f"Memory: {psutil.virtual_memory().total / (1024**3):.2f} GB total")
logger.info(f"Available memory: {psutil.virtual_memory().available / (1024**3):.2f} GB")
logger.info(f"Process ID: {os.getpid()}")
logger.info("="*60)
def log_exception(logger, exc_info=None):
"""Log exception with full traceback"""
if exc_info is None:
exc_info = sys.exc_info()
logger.error("EXCEPTION OCCURRED", exc_info=exc_info)
# Also log memory usage at time of crash
try:
import psutil
process = psutil.Process()
memory_info = process.memory_info()
system_memory = psutil.virtual_memory()
swap_memory = psutil.swap_memory()
logger.error(f"System memory at crash: {system_memory.percent:.1f}% used, "
f"{system_memory.available / (1024**3):.2f} GB available")
logger.error(f"Swap memory at crash: {swap_memory.percent:.1f}% used, "
f"{swap_memory.used / (1024**3):.2f} GB used")
logger.error(f"Process memory at crash: RSS={memory_info.rss / (1024**3):.2f} GB, "
f"VMS={memory_info.vms / (1024**3):.2f} GB")
logger.error(f"CPU usage at crash: {process.cpu_percent()}%")
except Exception as e:
logger.error(f"Could not get resource usage: {e}")
def log_memory_warning(logger, usage):
"""Log memory warning with details"""
logger.warning(f"MEMORY WARNING: {usage['memory_percent']:.1f}% memory used, "
f"{usage['memory_available_gb']:.1f} GB available")
if usage['swap_percent'] > 0:
logger.warning(f"SWAP WARNING: {usage['swap_percent']:.1f}% swap used, "
f"{usage['swap_used_gb']:.1f} GB used")
class DualLogger:
"""Wrapper class to provide print-like interface with dual logging"""
def __init__(self, logger):
self.logger = logger
def print(self, *args, **kwargs):
"""Print to both terminal and file"""
# Convert args to string like print() would
message = ' '.join(str(arg) for arg in args)
self.logger.info(message)
def error(self, *args, **kwargs):
"""Log error message"""
message = ' '.join(str(arg) for arg in args)
self.logger.error(message)
def warning(self, *args, **kwargs):
"""Log warning message"""
message = ' '.join(str(arg) for arg in args)
self.logger.warning(message)
def debug(self, *args, **kwargs):
"""Log debug message"""
message = ' '.join(str(arg) for arg in args)
self.logger.debug(message)