fix: logging, warnings, and soft-delete consistency

- Fix duplicate logging in multi-worker mode with file lock for cleanup scheduler
- Add Pydantic V2 model_config to suppress protected_namespaces warning
- Suppress PaddlePaddle ccache warnings
- Fix admin.py using non-existent User.username (now uses email)
- Fix get_user_stats to exclude soft-deleted tasks from statistics
- Fix create_task to exclude soft-deleted tasks from user limit check
- Change LOG_LEVEL default to INFO

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-14 15:40:31 +08:00
parent f46402f6c9
commit 7233e9cb7b
6 changed files with 132 additions and 43 deletions

View File

@@ -3,6 +3,11 @@ Tool_OCR - FastAPI Application Entry Point (V2)
Main application setup with CORS, routes, and startup/shutdown events
"""
import warnings
# Suppress noisy third-party warnings
warnings.filterwarnings("ignore", message=".*ccache.*")
warnings.filterwarnings("ignore", message=".*No ccache found.*")
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
@@ -107,27 +112,55 @@ def setup_signal_handlers():
# Ensure log directory exists before configuring logging
Path(settings.log_file).parent.mkdir(parents=True, exist_ok=True)
# Configure logging - Force configuration to override uvicorn's settings
logging.basicConfig(
level=getattr(logging, settings.log_level),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler(settings.log_file),
logging.StreamHandler(),
],
force=True # Force reconfiguration (Python 3.8+)
)
# Configure logging - prevent duplicate handlers
def setup_logging():
"""Configure logging with deduplication"""
log_level = getattr(logging, settings.log_level, logging.INFO)
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Also explicitly configure root logger and app loggers
root_logger = logging.getLogger()
root_logger.setLevel(getattr(logging, settings.log_level))
# Get root logger
root_logger = logging.getLogger()
# Configure app-specific loggers
for logger_name in ['app', 'app.services', 'app.services.pdf_generator_service', 'app.services.ocr_service']:
app_logger = logging.getLogger(logger_name)
app_logger.setLevel(getattr(logging, settings.log_level))
app_logger.propagate = True # Ensure logs propagate to root logger
# Clear existing handlers to prevent duplicates
root_logger.handlers.clear()
# Set root level
root_logger.setLevel(log_level)
# Create formatter
formatter = logging.Formatter(log_format)
# File handler
file_handler = logging.FileHandler(settings.log_file)
file_handler.setLevel(log_level)
file_handler.setFormatter(formatter)
root_logger.addHandler(file_handler)
# Stream handler (console)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(log_level)
stream_handler.setFormatter(formatter)
root_logger.addHandler(stream_handler)
# Suppress uvicorn's duplicate access logs
logging.getLogger("uvicorn.access").handlers.clear()
logging.getLogger("uvicorn.error").handlers.clear()
# Configure uvicorn loggers to use our handlers
for uvi_logger_name in ["uvicorn", "uvicorn.access", "uvicorn.error"]:
uvi_logger = logging.getLogger(uvi_logger_name)
uvi_logger.handlers.clear()
uvi_logger.propagate = True
uvi_logger.setLevel(log_level)
# Configure app-specific loggers (no separate handlers, just propagate)
for logger_name in ['app', 'app.services', 'app.routers']:
app_logger = logging.getLogger(logger_name)
app_logger.handlers.clear() # Remove any existing handlers
app_logger.setLevel(log_level)
app_logger.propagate = True # Propagate to root logger
setup_logging()
logger = logging.getLogger(__name__)