SPOC_V1 / logging_config.py
JatinAutonomousLabs's picture
Update logging_config.py
7fcecc9 verified
raw
history blame
5.8 kB
# logging_config.py - Production-ready logging configuration
import logging
import logging.handlers
import sys
import os
from typing import Optional
def setup_logging(log_level: str = "INFO", log_dir: str = "logs") -> None:
"""
Configures structured logging for the AI Lab with rotation and proper encoding.
Args:
log_level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
log_dir: Directory for log files
"""
try:
os.makedirs(log_dir, exist_ok=True)
except Exception as e:
print(f"Error creating log directory: {e}")
sys.exit(1)
# Create formatters
detailed_formatter = logging.Formatter(
fmt="%(asctime)s [%(levelname)-8s] [%(name)-20s] %(funcName)-15s:%(lineno)-4d | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
simple_formatter = logging.Formatter(
fmt="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%H:%M:%S"
)
# Create handlers
handlers = []
# Rotating file handler with UTF-8 encoding
try:
file_handler = logging.handlers.RotatingFileHandler(
filename=os.path.join(log_dir, "ai_lab.log"),
maxBytes=10 * 1024 * 1024, # 10MB per file
backupCount=5, # Keep 5 backup files
encoding='utf-8',
mode='a'
)
file_handler.setFormatter(detailed_formatter)
file_handler.setLevel(getattr(logging, log_level))
handlers.append(file_handler)
except Exception as e:
print(f"Warning: Could not create file handler: {e}")
# Console handler with UTF-8 support
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(simple_formatter)
console_handler.setLevel(logging.INFO) # Console shows INFO and above
# Ensure UTF-8 encoding on Windows
if hasattr(console_handler.stream, 'reconfigure'):
console_handler.stream.reconfigure(encoding='utf-8')
handlers.append(console_handler)
# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, log_level))
# Remove any existing handlers
for handler in root_logger.handlers[:]:
root_logger.removeHandler(handler)
# Add new handlers
for handler in handlers:
root_logger.addHandler(handler)
# Configure third-party library logging levels
noisy_libraries = [
"httpx",
"urllib3",
"sentence_transformers",
"transformers",
"faiss",
"openai",
"httpcore",
"langchain"
]
for lib in noisy_libraries:
logging.getLogger(lib).setLevel(logging.WARNING)
# Log startup message
logging.info("="*60)
logging.info("AI Lab Logging System Initialized")
logging.info(f"Log Level: {log_level}")
logging.info(f"Log Directory: {os.path.abspath(log_dir)}")
logging.info("="*60)
def get_logger(name: str) -> logging.Logger:
"""
Get a logger instance for a specific module.
Args:
name: Name of the module/component
Returns:
Configured logger instance
"""
return logging.getLogger(name)
def log_exception(logger: logging.Logger, e: Exception, context: str = "") -> None:
"""
Helper function to log exceptions with full traceback.
Args:
logger: Logger instance to use
e: Exception to log
context: Additional context about where the exception occurred
"""
import traceback
error_msg = f"Exception in {context}: {str(e)}" if context else str(e)
logger.error(error_msg)
logger.debug(f"Traceback:\n{traceback.format_exc()}")
def setup_performance_logging() -> Optional[logging.Logger]:
"""
Set up a separate performance logger for tracking execution times and metrics.
Returns:
Performance logger instance
"""
perf_logger = logging.getLogger("performance")
perf_logger.setLevel(logging.DEBUG)
# Create performance log file
try:
perf_handler = logging.handlers.RotatingFileHandler(
filename=os.path.join("logs", "performance.log"),
maxBytes=5 * 1024 * 1024, # 5MB
backupCount=3,
encoding='utf-8'
)
perf_formatter = logging.Formatter(
fmt="%(asctime)s.%(msecs)03d | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
perf_handler.setFormatter(perf_formatter)
perf_logger.addHandler(perf_handler)
return perf_logger
except Exception as e:
print(f"Warning: Could not create performance logger: {e}")
return None
# Context manager for timed operations
class LoggedTimer:
"""Context manager for logging operation execution time."""
def __init__(self, logger: logging.Logger, operation_name: str):
self.logger = logger
self.operation_name = operation_name
self.start_time = None
def __enter__(self):
import time
self.start_time = time.time()
self.logger.debug(f"Starting: {self.operation_name}")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
import time
elapsed = time.time() - self.start_time
if exc_type:
self.logger.error(f"Failed: {self.operation_name} after {elapsed:.2f}s - {exc_val}")
else:
self.logger.debug(f"Completed: {self.operation_name} in {elapsed:.2f}s")
# Initialize logging when module is imported (can be overridden)
if __name__ != "__main__":
# Auto-initialize with defaults when imported
try:
setup_logging()
except Exception as e:
print(f"Warning: Auto-initialization of logging failed: {e}")