- Create logging infrastructure in src/infrastructure/logging/ - logger.py: Main logging setup with console and file handlers - uvicorn_config.py: Custom uvicorn logging configuration - __init__.py: Export public logging API - Update FastAPI application to use logging - Replace all print() statements with proper logger calls - Initialize logging during application startup - Add detailed startup/shutdown logging - Add startup scripts - run_server.py: Python script with uvicorn logging config - start_server.sh: Bash wrapper script - Add comprehensive documentation - docs/logging.md: User guide for logging system - docs/logging_implementation_summary.md: Technical implementation details Features: - Console logging with clean, readable format - File logging with timestamps to logs/fastapi_app.log - Configurable log level via LOG_LEVEL environment variable - Proper lazy formatting for performance - Captures all uvicorn, application, and module logs - Automatic log directory creation
101 lines
2.8 KiB
Python
101 lines
2.8 KiB
Python
"""
|
|
Logging configuration for the Aniworld application.
|
|
|
|
This module provides a centralized logging setup with both console and file
|
|
logging, following Python logging best practices.
|
|
"""
|
|
import logging
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from src.config.settings import settings
|
|
|
|
|
|
def setup_logging(
|
|
log_file: Optional[str] = None,
|
|
log_level: Optional[str] = None,
|
|
log_dir: Optional[Path] = None
|
|
) -> logging.Logger:
|
|
"""
|
|
Configure application logging with console and file handlers.
|
|
|
|
Args:
|
|
log_file: Name of the log file (default: "fastapi_app.log")
|
|
log_level: Logging level (default: from settings or "INFO")
|
|
log_dir: Directory for log files (default: "logs" in project root)
|
|
|
|
Returns:
|
|
Configured logger instance
|
|
"""
|
|
# Determine log level
|
|
level_name = log_level or settings.log_level or "INFO"
|
|
level = getattr(logging, level_name.upper(), logging.INFO)
|
|
|
|
# Determine log directory and file
|
|
if log_dir is None:
|
|
# Default to logs directory in project root
|
|
log_dir = Path(__file__).parent.parent.parent.parent / "logs"
|
|
|
|
log_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
if log_file is None:
|
|
log_file = "fastapi_app.log"
|
|
|
|
log_path = log_dir / log_file
|
|
|
|
# Create formatters
|
|
detailed_formatter = logging.Formatter(
|
|
fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
datefmt="%Y-%m-%d %H:%M:%S"
|
|
)
|
|
|
|
console_formatter = logging.Formatter(
|
|
fmt="%(levelname)s: %(message)s"
|
|
)
|
|
|
|
# Configure root logger
|
|
root_logger = logging.getLogger()
|
|
root_logger.setLevel(level)
|
|
|
|
# Remove existing handlers to avoid duplicates
|
|
root_logger.handlers.clear()
|
|
|
|
# Console handler (stdout)
|
|
console_handler = logging.StreamHandler(sys.stdout)
|
|
console_handler.setLevel(level)
|
|
console_handler.setFormatter(console_formatter)
|
|
root_logger.addHandler(console_handler)
|
|
|
|
# File handler
|
|
file_handler = logging.FileHandler(log_path, mode='a', encoding='utf-8')
|
|
file_handler.setLevel(level)
|
|
file_handler.setFormatter(detailed_formatter)
|
|
root_logger.addHandler(file_handler)
|
|
|
|
# Create application logger
|
|
logger = logging.getLogger("aniworld")
|
|
logger.setLevel(level)
|
|
|
|
# Log startup information
|
|
logger.info("=" * 60)
|
|
logger.info("Logging configured successfully")
|
|
logger.info("Log level: %s", level_name.upper())
|
|
logger.info("Log file: %s", log_path)
|
|
logger.info("=" * 60)
|
|
|
|
return logger
|
|
|
|
|
|
def get_logger(name: str) -> logging.Logger:
|
|
"""
|
|
Get a logger instance for a specific module.
|
|
|
|
Args:
|
|
name: Name of the logger (typically __name__)
|
|
|
|
Returns:
|
|
Logger instance
|
|
"""
|
|
return logging.getLogger(name)
|