full-stack-fastapi-template
full-stack-fastapi-template copied to clipboard
feat: Add comprehensive analytics API with OpenTelemetry observability
Overview
This PR introduces a comprehensive analytics system with OpenTelemetry instrumentation for enhanced observability and monitoring capabilities.
Features Added
Analytics API Endpoints
-
User Analytics (
/api/v1/analytics/user-summary):- Total user count
- Active/inactive user distribution
- Signup trends (when creation timestamps are available)
-
Item Analytics (
/api/v1/analytics/item-trends):- Total item count
- Creation trends (when creation timestamps are available)
OpenTelemetry Integration
- Distributed Tracing: Full request tracing across the application
- Database Instrumentation: SQLAlchemy query monitoring
- FastAPI Auto-instrumentation: Automatic HTTP request/response tracing
- CI-Friendly Configuration: OTLP exporter only activates when endpoint is explicitly configured
- Production Ready: No connection timeouts in test/CI environments
Performance Optimizations
- Polars Integration: Lightning-fast in-memory data processing for analytics
- Efficient Data Aggregation: Optimized queries with minimal memory footprint
- Structured Response Models: Type-safe Pydantic models with modern Python 3.9+ annotations
Technical Implementation
New Dependencies
polars # High-performance DataFrame library
duckdb # In-memory analytical database
opentelemetry-api # OpenTelemetry core API
opentelemetry-sdk # OpenTelemetry SDK
opentelemetry-exporter-otlp # OTLP protocol exporter
opentelemetry-instrumentation-fastapi # FastAPI auto-instrumentation
opentelemetry-instrumentation-sqlalchemy # SQLAlchemy instrumentation
File Changes
- ✅
backend/app/api/routes/analytics.py- New analytics endpoints (202 lines) - ✅
backend/app/core/telemetry.py- OpenTelemetry configuration (47 lines) - ✅
backend/app/tests/api/test_analytics.py- Comprehensive test coverage (56 lines) - ✅
backend/app/api/main.py- Router registration - ✅
backend/app/main.py- Telemetry initialization - ✅
backend/pyproject.toml- New dependencies - ✅
README.md- Updated documentation
Configuration
Environment Variables
# OpenTelemetry configuration (optional - prevents CI connection issues)
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" # Your OTLP collector
OTEL_SERVICE_NAME="fastapi-application" # Service name in traces
Code Quality & CI
- Type Safety: Full MyPy compliance with proper type annotations
- Modern Python: Uses
list/dictinstead of deprecatedtyping.List/typing.Dict - Linting: All Ruff checks pass with modern Python style
- Pre-commit Hooks: All formatting and style checks pass
- CI-Ready: OpenTelemetry configuration prevents connection timeouts in test environments
- Import Optimization: Clean, organized import blocks with no unused imports
- Return Types: Explicit return type annotations for all functions
Testing
- ✅ Complete test coverage for all analytics endpoints
- ✅ Robust error handling for empty datasets and missing timestamps
- ✅ Compatible with existing test infrastructure
- ✅ CI-friendly configuration (no external service dependencies)
- ✅ MyPy type checking compliance
Benefits
- Enhanced Monitoring: Deep insights into application performance and user behavior
- Scalable Analytics: Efficient data processing suitable for large datasets
- Production Ready: Enterprise-grade observability with OpenTelemetry standards
- Developer Experience: Type-safe APIs with comprehensive documentation and full type coverage
- CI/CD Friendly: No external dependencies, passes all quality checks
- Maintainable: Clean code with proper type annotations and formatting
Future Enhancements
- User signup trends (requires
created_atfield in User model) - Item creation trends (requires
created_atfield in Item model) - Advanced analytics dashboards
- Real-time metrics and alerting
Could a maintainer please add the feature label to this PR? It's needed for the CI checks to pass. This PR adds new analytics functionality with OpenTelemetry observability.
This seems like a feature or set of features that would belong in your own project and not here in the template, which should be a simple baseline for everyone to build on top. For now, I'll pass on this one here. :coffee: