feat: Complete v1.1.1 Phases 2 & 3 - Enhancements and Polish

Phase 2 - Enhancements:
- Add performance monitoring infrastructure with MetricsBuffer
- Implement three-tier health checks (/health, /health?detailed, /admin/health)
- Enhance search with FTS5 fallback and XSS-safe highlighting
- Add Unicode slug generation with timestamp fallback
- Expose database pool statistics via /admin/metrics
- Create missing error templates (400, 401, 403, 405, 503)

Phase 3 - Polish:
- Implement RSS streaming optimization (memory O(n) → O(1))
- Add admin metrics dashboard with htmx and Chart.js
- Fix flaky migration race condition tests
- Create comprehensive operational documentation
- Add upgrade guide and troubleshooting guide

Testing: 632 tests passing, zero flaky tests
Documentation: Complete operational guides
Security: All security reviews passed

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-25 20:10:41 -07:00
parent 93d2398c1d
commit 07fff01fab
25 changed files with 4371 additions and 142 deletions

View File

@@ -180,47 +180,89 @@ def create_app(config=None):
"""
Health check endpoint for containers and monitoring
Per developer Q&A Q10:
- Basic mode (/health): Public, no auth, returns 200 OK for load balancers
- Detailed mode (/health?detailed=true): Requires auth, checks database/disk
Returns:
JSON with status and basic info
JSON with status and info (varies by mode)
Response codes:
200: Application healthy
401: Unauthorized (detailed mode without auth)
500: Application unhealthy
Checks:
- Database connectivity
- File system access
- Basic application state
Query parameters:
detailed: If 'true', perform detailed checks (requires auth)
"""
from flask import jsonify
from flask import jsonify, request
import os
import shutil
# Check if detailed mode requested
detailed = request.args.get('detailed', '').lower() == 'true'
if detailed:
# Detailed mode requires authentication
if not g.get('me'):
return jsonify({"error": "Authentication required for detailed health check"}), 401
# Perform comprehensive health checks
checks = {}
overall_healthy = True
try:
# Check database connectivity
from starpunk.database import get_db
db = get_db(app)
db.execute("SELECT 1").fetchone()
db.close()
try:
from starpunk.database import get_db
db = get_db(app)
db.execute("SELECT 1").fetchone()
db.close()
checks['database'] = {'status': 'healthy', 'message': 'Database accessible'}
except Exception as e:
checks['database'] = {'status': 'unhealthy', 'error': str(e)}
overall_healthy = False
# Check filesystem access
data_path = app.config.get("DATA_PATH", "data")
if not os.path.exists(data_path):
raise Exception("Data path not accessible")
try:
data_path = app.config.get("DATA_PATH", "data")
if not os.path.exists(data_path):
raise Exception("Data path not accessible")
checks['filesystem'] = {'status': 'healthy', 'path': data_path}
except Exception as e:
checks['filesystem'] = {'status': 'unhealthy', 'error': str(e)}
overall_healthy = False
return (
jsonify(
{
"status": "healthy",
"version": app.config.get("VERSION", __version__),
"environment": app.config.get("ENV", "unknown"),
}
),
200,
)
# Check disk space
try:
data_path = app.config.get("DATA_PATH", "data")
stat = shutil.disk_usage(data_path)
percent_free = (stat.free / stat.total) * 100
checks['disk'] = {
'status': 'healthy' if percent_free > 10 else 'warning',
'total_gb': round(stat.total / (1024**3), 2),
'free_gb': round(stat.free / (1024**3), 2),
'percent_free': round(percent_free, 2)
}
if percent_free <= 5:
overall_healthy = False
except Exception as e:
checks['disk'] = {'status': 'unhealthy', 'error': str(e)}
overall_healthy = False
except Exception as e:
return jsonify({"status": "unhealthy", "error": str(e)}), 500
return jsonify({
"status": "healthy" if overall_healthy else "unhealthy",
"version": app.config.get("VERSION", __version__),
"environment": app.config.get("ENV", "unknown"),
"checks": checks
}), 200 if overall_healthy else 500
else:
# Basic mode - just return 200 OK (for load balancers)
# No authentication required, minimal checks
return jsonify({
"status": "ok",
"version": app.config.get("VERSION", __version__)
}), 200
return app