121 lines
3.6 KiB
Python
121 lines
3.6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
|
||
|
|
"""
|
||
|
|
Logger module for the Icecast metadata IRC announcer.
|
||
|
|
Uses Loguru for simple yet powerful logging.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
from loguru import logger
|
||
|
|
|
||
|
|
class LogManager:
|
||
|
|
"""
|
||
|
|
Manages logging configuration for the Icecast metadata IRC announcer.
|
||
|
|
|
||
|
|
This class provides a simple interface for configuring and using Loguru
|
||
|
|
throughout the project. It handles log file rotation, formatting, and
|
||
|
|
different log levels.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def __init__(self, config=None):
|
||
|
|
"""
|
||
|
|
Initialize the LogManager with optional configuration.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
config: Optional dictionary with logging configuration.
|
||
|
|
If None, default configuration is used.
|
||
|
|
"""
|
||
|
|
self.config = config or {}
|
||
|
|
self.log_dir = Path(self.config.get('log_dir', 'logs'))
|
||
|
|
self.log_level = self.config.get('level', 'INFO').upper()
|
||
|
|
self.log_format = self.config.get('format',
|
||
|
|
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
|
||
|
|
"<level>{level: <8}</level> | "
|
||
|
|
"<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - "
|
||
|
|
"<level>{message}</level>"
|
||
|
|
)
|
||
|
|
|
||
|
|
# Create log directory if it doesn't exist
|
||
|
|
if not self.log_dir.exists():
|
||
|
|
self.log_dir.mkdir(parents=True, exist_ok=True)
|
||
|
|
|
||
|
|
# Configure logger
|
||
|
|
self._configure_logger()
|
||
|
|
|
||
|
|
def _configure_logger(self):
|
||
|
|
"""Configure Loguru logger with appropriate sinks and formats."""
|
||
|
|
# Remove default handler
|
||
|
|
logger.remove()
|
||
|
|
|
||
|
|
# Add console handler
|
||
|
|
logger.add(
|
||
|
|
sys.stderr,
|
||
|
|
format=self.log_format,
|
||
|
|
level=self.log_level,
|
||
|
|
colorize=True
|
||
|
|
)
|
||
|
|
|
||
|
|
# Add file handler with rotation
|
||
|
|
log_file = self.log_dir / "icecast_bot.log"
|
||
|
|
logger.add(
|
||
|
|
str(log_file),
|
||
|
|
format=self.log_format,
|
||
|
|
level=self.log_level,
|
||
|
|
rotation="10 MB", # Rotate when file reaches 10MB
|
||
|
|
compression="zip", # Compress rotated logs
|
||
|
|
retention="1 week", # Keep logs for 1 week
|
||
|
|
backtrace=True, # Include backtrace in error logs
|
||
|
|
diagnose=True # Include variables in error logs
|
||
|
|
)
|
||
|
|
|
||
|
|
def get_logger(self, name=None):
|
||
|
|
"""
|
||
|
|
Get a logger instance with the given name.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
name: Optional name for the logger. If None, the calling module's name is used.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
A Loguru logger instance.
|
||
|
|
"""
|
||
|
|
if name:
|
||
|
|
return logger.bind(name=name)
|
||
|
|
return logger
|
||
|
|
|
||
|
|
@staticmethod
|
||
|
|
def set_level(level):
|
||
|
|
"""
|
||
|
|
Set the log level for all handlers.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||
|
|
"""
|
||
|
|
for handler_id in logger._core.handlers:
|
||
|
|
logger.configure(handler_id, level=level)
|
||
|
|
|
||
|
|
# Create a default instance for easy import
|
||
|
|
log_manager = LogManager()
|
||
|
|
get_logger = log_manager.get_logger
|
||
|
|
|
||
|
|
# Export the logger directly for simple usage
|
||
|
|
log = logger
|
||
|
|
|
||
|
|
# For convenience, export common log levels
|
||
|
|
debug = logger.debug
|
||
|
|
info = logger.info
|
||
|
|
warning = logger.warning
|
||
|
|
error = logger.error
|
||
|
|
critical = logger.critical
|
||
|
|
exception = logger.exception
|
||
|
|
|
||
|
|
# Example usage:
|
||
|
|
# from logger import log, debug, info, error
|
||
|
|
# log.info("This is an info message")
|
||
|
|
# debug("This is a debug message")
|
||
|
|
#
|
||
|
|
# # Or with a named logger:
|
||
|
|
# from logger import get_logger
|
||
|
|
# logger = get_logger("my_module")
|
||
|
|
# logger.info("This is a message from my_module")
|