Add production logging, datetime fixes, and session tests

DateTime Timezone Handling (Critical Bug Fix):
- Updated all models to use DateTime(timezone=True) for PostgreSQL
- Changed datetime defaults to lambda: datetime.now(timezone.utc)
- Fixed mixing of timezone-aware and timezone-naive datetime objects
- Resolved Internal Server Errors in session completion endpoint
- Affected models: User, Team, Tree, Session, Attachment

Production Logging System:
- Created logging_config.py with structured logging setup
- Added log rotation (10MB files, 10 backups) for production
- Implemented RequestLoggingMiddleware with correlation IDs
- Added ErrorLoggingMiddleware for comprehensive error tracking
- Integrated logging into main.py application startup
- Supports dev/prod modes with appropriate log levels

Integration Tests - Session Workflow:
- Created test_sessions.py with 12 comprehensive tests
- Session lifecycle: create, update, complete
- Session export in multiple formats (markdown, text, HTML)
- Error handling and authorization checks
- Added pytest.ini with coverage configuration
- Added requirements-dev.txt with pytest dependencies

Following 2026 FastAPI best practices for timezone handling and structured logging.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-01-27 20:39:09 -05:00
parent aa54b6c192
commit 7d96807fb1
10 changed files with 639 additions and 17 deletions

View File

@@ -1,21 +1,30 @@
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.core.database import init_db
from app.core.logging_config import setup_logging
from app.core.middleware import RequestLoggingMiddleware, ErrorLoggingMiddleware
from app.api.router import api_router
# Initialize logging configuration
setup_logging()
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan handler."""
# Startup
logger.info("Starting Apoklisis API server...")
logger.info(f"Environment: {'Development' if settings.DEBUG else 'Production'}")
# Note: In production, use Alembic migrations instead of init_db
# await init_db()
yield
# Shutdown
pass
logger.info("Shutting down Apoklisis API server...")
app = FastAPI(
@@ -28,6 +37,10 @@ app = FastAPI(
lifespan=lifespan
)
# Add logging middleware (BEFORE CORS to log all requests)
app.add_middleware(ErrorLoggingMiddleware)
app.add_middleware(RequestLoggingMiddleware)
# Configure CORS
app.add_middleware(
CORSMiddleware,