DocUA's picture
add .env
2929135
raw
history blame
3.29 kB
# src/utils/logger.py
import logging
import sys
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
from pathlib import Path
from datetime import datetime
from typing import Optional
from ..config.settings import Settings
class CustomFormatter(logging.Formatter):
"""Custom formatter with color coding for different log levels"""
COLORS = {
'DEBUG': '\033[0;36m', # Cyan
'INFO': '\033[0;32m', # Green
'WARNING': '\033[0;33m', # Yellow
'ERROR': '\033[0;31m', # Red
'CRITICAL': '\033[0;37;41m' # White on Red
}
RESET = '\033[0m'
def format(self, record):
# Add color to log level if on console
if hasattr(self, 'use_color') and self.use_color:
record.levelname = f"{self.COLORS.get(record.levelname, '')}{record.levelname}{self.RESET}"
return super().format(record)
def setup_logger(
name: str,
log_level: Optional[str] = None,
log_file: Optional[str] = None
) -> logging.Logger:
"""
Set up logger with both file and console handlers
Args:
name: Logger name
log_level: Optional override for log level
log_file: Optional override for log file path
Returns:
Configured logger instance
"""
try:
# Create logger
logger = logging.getLogger(name)
logger.setLevel(log_level or Settings.LOG_LEVEL)
# Avoid adding handlers if they already exist
if logger.handlers:
return logger
# Create formatters
file_formatter = logging.Formatter(
'%(asctime)s - %(name)s - [%(levelname)s] - %(message)s'
)
console_formatter = CustomFormatter(
'%(asctime)s - %(name)s - [%(levelname)s] - %(message)s'
)
console_formatter.use_color = True
# Create and configure file handler
log_file = log_file or Settings.LOG_FILE
log_dir = Path(log_file).parent
log_dir.mkdir(parents=True, exist_ok=True)
# Rotating file handler (size-based)
file_handler = RotatingFileHandler(
log_file,
maxBytes=10 * 1024 * 1024, # 10MB
backupCount=5
)
file_handler.setFormatter(file_formatter)
# Time-based rotating handler for daily logs
daily_handler = TimedRotatingFileHandler(
str(log_dir / f"daily_{datetime.now():%Y-%m-%d}.log"),
when="midnight",
interval=1,
backupCount=30
)
daily_handler.setFormatter(file_formatter)
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(console_formatter)
# Add handlers
logger.addHandler(file_handler)
logger.addHandler(daily_handler)
logger.addHandler(console_handler)
return logger
except Exception as e:
# Fallback to basic logging if setup fails
basic_logger = logging.getLogger(name)
basic_logger.setLevel(logging.INFO)
basic_logger.addHandler(logging.StreamHandler(sys.stdout))
basic_logger.error(f"Error setting up logger: {str(e)}")
return basic_logger# Logging configuration implementation