vibeon-translator / utils /logger.py
Vibeon Deploy Bot
deploy: vibeon-translator 2026-08-23T13:56:02Z
2909918
Raw
History Blame Contribute Delete
3.08 kB
"""
Logging Configuration Utility
Provides centralized logging setup for the Vibeon Translator API
"""
import logging
import sys
from pathlib import Path
import uuid
from typing import Callable, Optional
from starlette.middleware.base import BaseHTTPMiddleware # type: ignore
from starlette.requests import Request # type: ignore
def setup_logging(log_level: str = "INFO", log_file: Optional[str] = None):
"""
Setup logging configuration for the application
Args:
log_level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
log_file: Optional log file path
"""
# Create formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Get root logger
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, log_level.upper()))
# Clear existing handlers
root_logger.handlers.clear()
# Console handler with UTF-8 encoding for Unicode support
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
# Force UTF-8 encoding to handle Unicode characters (Kinyarwanda, Hindi, etc.)
if hasattr(sys.stdout, 'reconfigure'):
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
except Exception:
pass # Fallback silently if reconfigure not available
root_logger.addHandler(console_handler)
# File handler if log file is specified
if log_file:
# Create log directory if it doesn't exist
log_path = Path(log_file)
log_path.parent.mkdir(parents=True, exist_ok=True)
# Use UTF-8 encoding for file handler as well
file_handler = logging.FileHandler(log_file, encoding='utf-8', errors='replace')
file_handler.setFormatter(formatter)
root_logger.addHandler(file_handler)
# Set specific log levels for noisy libraries
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("transformers").setLevel(logging.WARNING)
logging.getLogger("torch").setLevel(logging.WARNING)
return root_logger
class RequestIdLoggingMiddleware(BaseHTTPMiddleware):
"""Attach request ID header and log structured request/response"""
async def dispatch(self, request: Request, call_next: Callable):
request_id = request.headers.get("X-Request-ID") or str(uuid.uuid4())
request.state.request_id = request_id
logger = logging.getLogger("request")
try:
response = await call_next(request)
response.headers["X-Request-ID"] = request_id
logger.info(
"method=%s path=%s status=%s request_id=%s",
request.method,
str(request.url.path),
response.status_code,
request_id,
)
return response
except Exception:
logger.exception("error request_id=%s", request_id)
raise