abhisheksan's picture
Refactor logging setup: enhance file logging configuration and adjust log directory handling
cda1137
"""Structured logging setup using loguru - Container optimized."""
import sys
import os
from pathlib import Path
from loguru import logger
from app.core.config import settings
def setup_logging() -> None:
"""Configure structured logging with loguru."""
# Remove default handler
logger.remove()
# Always add console handler with custom format
logger.add(
sys.stdout,
level=settings.log_level,
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>",
colorize=True
)
# Only add file logging in development or when explicitly enabled
if _should_enable_file_logging():
_setup_file_logging()
else:
logger.info("File logging disabled - using stdout only (recommended for containers)")
def _should_enable_file_logging() -> bool:
"""Determine if file logging should be enabled."""
# Check explicit environment variable
disable_file_logging = os.getenv("DISABLE_FILE_LOGGING", "false").lower()
if disable_file_logging == "true":
return False
# Check if we're likely in a container environment
container_indicators = [
os.getenv("CONTAINER_ENV") == "true",
os.path.exists("/.dockerenv"),
os.getenv("KUBERNETES_SERVICE_HOST") is not None,
os.getenv("RAILWAY_ENVIRONMENT") is not None,
os.getenv("RENDER") is not None,
os.getenv("HEROKU") is not None,
]
if any(container_indicators):
return False
# Try to write to the logs directory
try:
log_dir = _get_log_directory()
test_file = log_dir / ".write_test"
test_file.write_text("test")
test_file.unlink()
return True
except (OSError, PermissionError):
return False
def _setup_file_logging() -> None:
"""Set up file-based logging handlers."""
log_dir = _get_log_directory()
# Add file handler for errors
logger.add(
log_dir / "error.log",
level="ERROR",
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
rotation="10 MB",
retention="30 days",
compression="zip"
)
# Add file handler for all logs
logger.add(
log_dir / "app.log",
level="INFO",
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
rotation="50 MB",
retention="7 days",
compression="zip"
)
logger.info(f"File logging enabled. Logs directory: {log_dir}")
def _get_log_directory() -> Path:
"""Get the appropriate log directory based on environment."""
# Check for custom log directory from environment
custom_log_dir = os.getenv("LOG_DIR")
if custom_log_dir:
log_dir = Path(custom_log_dir)
else:
# Default to logs/ directory
log_dir = Path("logs")
# Create directory if it doesn't exist
log_dir.mkdir(parents=True, exist_ok=True)
return log_dir
def get_logger(name: str):
"""Get a logger instance for a specific module."""
return logger.bind(name=name)