HuggingClaw-Cain / utils /logger.py
Claude Code
Claude Code: Cain is running successfully. Let's implement a robust error logging sys
30a95a7
"""
Cain Error Logging System with Rotation and Severity Levels
Features:
- RotatingFileHandler with 1MB max size and 3 backup files
- Severity levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
- Timestamp and severity formatted in log messages
- Separate error log file for easier debugging
"""
import logging
import sys
from pathlib import Path
from logging.handlers import RotatingFileHandler
from datetime import datetime
# Severity levels mapping
SEVERITY_LEVELS = {
'DEBUG': logging.DEBUG,
'INFO': logging.INFO,
'WARNING': logging.WARNING,
'ERROR': logging.ERROR,
'CRITICAL': logging.CRITICAL
}
# Default log format with timestamp and severity
LOG_FORMAT = '%(asctime)s | %(levelname)-8s | %(name)s | %(message)s'
DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
# Log file paths
LOGS_DIR = Path("logs")
ERRORS_LOG = LOGS_DIR / "errors.log"
def setup_error_logger(log_dir: Path = None, max_bytes: int = 1024*1024, backup_count: int = 3):
"""
Configure the error logging system with rotating file handler.
Args:
log_dir: Directory for log files (default: ./logs)
max_bytes: Max size per log file before rotation (default: 1MB)
backup_count: Number of backup files to keep (default: 3)
Returns:
logging.Logger: Configured logger instance
"""
global LOGS_DIR, ERRORS_LOG
if log_dir:
LOGS_DIR = log_dir
ERRORS_LOG = LOGS_DIR / "errors.log"
# Ensure logs directory exists
LOGS_DIR.mkdir(exist_ok=True)
# Create or get logger
logger = logging.getLogger("cain_errors")
logger.setLevel(logging.DEBUG)
# Remove existing handlers to avoid duplicates
logger.handlers.clear()
# Create rotating file handler for error-specific logs
rotating_handler = RotatingFileHandler(
ERRORS_LOG,
maxBytes=max_bytes,
backupCount=backup_count,
encoding='utf-8'
)
rotating_handler.setLevel(logging.DEBUG)
# Create formatter with timestamp and severity
formatter = logging.Formatter(LOG_FORMAT, DATE_FORMAT)
rotating_handler.setFormatter(formatter)
# Add handler to logger
logger.addHandler(rotating_handler)
# Also add console handler for visibility
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
def log_error(logger: logging.Logger, severity: str, message: str, **kwargs):
"""
Log an error with specified severity level.
Args:
logger: Logger instance
severity: One of: DEBUG, INFO, WARNING, ERROR, CRITICAL
message: Log message
**kwargs: Additional context to include in message
"""
severity_upper = severity.upper()
if severity_upper not in SEVERITY_LEVELS:
logger.warning(f"Invalid severity '{severity}', defaulting to ERROR")
severity_upper = 'ERROR'
# Add extra context if provided
if kwargs:
context = ' | '.join(f"{k}={v}" for k, v in kwargs.items())
message = f"{message} | {context}"
log_func = getattr(logger, severity_upper.lower())
log_func(message)
# Create default error logger instance
error_logger = setup_error_logger()