webui fixes

This commit is contained in:
Dobromir Popov
2025-08-05 16:05:05 +03:00
parent bf4d43f6f7
commit 468fa0dcd6
4 changed files with 244 additions and 89 deletions

View File

@ -4,7 +4,7 @@ REST API server for COBY system.
from fastapi import FastAPI, HTTPException, Request, Query, Path, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.responses import JSONResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from typing import Optional, List
import asyncio
@ -77,8 +77,6 @@ def create_app(config_obj=None) -> FastAPI:
redoc_url="/redoc"
)
# We'll mount static files AFTER defining all API routes to avoid conflicts
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
@ -98,58 +96,94 @@ def create_app(config_obj=None) -> FastAPI:
@app.websocket("/ws/dashboard")
async def websocket_endpoint(websocket: WebSocket):
"""WebSocket endpoint for dashboard real-time updates"""
"""WebSocket endpoint for real-time dashboard updates"""
await connection_manager.connect(websocket)
try:
while True:
# Send periodic updates
await asyncio.sleep(5) # Update every 5 seconds
# Gather system status
system_data = {
# Send periodic status updates
status_data = {
"type": "status",
"timestamp": time.time(),
"performance": {
"cpu_usage": 25.5, # Stub data
"memory_usage": 45.2,
"throughput": 1250,
"avg_latency": 12.3
},
"exchanges": {
"binance": "connected",
"coinbase": "connected",
"kraken": "disconnected",
"bybit": "connected"
},
"processing": {
"active": True,
"total_processed": 15420
}
"connections": len(connection_manager.active_connections),
"system": "healthy"
}
await connection_manager.send_personal_message(
json.dumps(system_data),
websocket
json.dumps(status_data), websocket
)
await asyncio.sleep(30) # Send update every 30 seconds
except WebSocketDisconnect:
connection_manager.disconnect(websocket)
except Exception as e:
logger.error(f"WebSocket error: {e}")
connection_manager.disconnect(websocket)
@app.get("/api/health")
async def api_health_check():
"""API Health check endpoint for dashboard"""
try:
# Check Redis connection
redis_healthy = await redis_manager.ping()
health_data = {
'status': 'healthy' if redis_healthy else 'degraded',
'redis': 'connected' if redis_healthy else 'disconnected',
'version': '1.0.0',
'timestamp': time.time()
}
return response_formatter.status_response(health_data)
except Exception as e:
logger.error(f"Health check failed: {e}")
return JSONResponse(
status_code=503,
content=response_formatter.error("Service unavailable", "HEALTH_CHECK_FAILED")
)
@app.get("/health")
async def health_check():
"""Health check endpoint"""
return response_formatter.health(healthy=True, components={
"api": {"healthy": True},
"cache": {"healthy": redis_manager.is_connected()},
"database": {"healthy": True} # Stub
})
try:
# Check Redis connection
redis_healthy = await redis_manager.ping()
health_data = {
'status': 'healthy' if redis_healthy else 'degraded',
'redis': 'connected' if redis_healthy else 'disconnected',
'version': '1.0.0'
}
return response_formatter.status_response(health_data)
except Exception as e:
logger.error(f"Health check failed: {e}")
return JSONResponse(
status_code=503,
content=response_formatter.error("Service unavailable", "HEALTH_CHECK_FAILED")
)
@app.get("/")
@app.get("/", response_class=HTMLResponse)
async def root():
"""Root endpoint - serve dashboard"""
return {"message": "COBY Multi-Exchange Data Aggregation System", "status": "running"}
"""Root endpoint - serve dashboard HTML"""
static_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "web", "static")
index_path = os.path.join(static_path, "index.html")
if os.path.exists(index_path):
with open(index_path, 'r', encoding='utf-8') as f:
return HTMLResponse(content=f.read())
else:
# Fallback if index.html doesn't exist
return HTMLResponse(content="""
<!DOCTYPE html>
<html>
<head><title>COBY System</title></head>
<body>
<h1>COBY Multi-Exchange Data Aggregation System</h1>
<p>System is running. Dashboard files not found.</p>
<p><a href="/api/health">Health Check</a></p>
</body>
</html>
""")
@app.middleware("http")
async def rate_limit_middleware(request: Request, call_next):
@ -203,53 +237,6 @@ def create_app(config_obj=None) -> FastAPI:
except Exception as e:
logger.error(f"API server shutdown error: {e}")
# API Health check endpoint (for dashboard)
@app.get("/api/health")
async def api_health_check():
"""API Health check endpoint for dashboard"""
try:
# Check Redis connection
redis_healthy = await redis_manager.ping()
health_data = {
'status': 'healthy' if redis_healthy else 'degraded',
'redis': 'connected' if redis_healthy else 'disconnected',
'version': '1.0.0',
'timestamp': time.time()
}
return response_formatter.status_response(health_data)
except Exception as e:
logger.error(f"Health check failed: {e}")
return JSONResponse(
status_code=503,
content=response_formatter.error("Service unavailable", "HEALTH_CHECK_FAILED")
)
# Health check endpoint
@app.get("/health")
async def health_check():
"""Health check endpoint"""
try:
# Check Redis connection
redis_healthy = await redis_manager.ping()
health_data = {
'status': 'healthy' if redis_healthy else 'degraded',
'redis': 'connected' if redis_healthy else 'disconnected',
'version': '1.0.0'
}
return response_formatter.status_response(health_data)
except Exception as e:
logger.error(f"Health check failed: {e}")
return JSONResponse(
status_code=503,
content=response_formatter.error("Service unavailable", "HEALTH_CHECK_FAILED")
)
# Heatmap endpoints
@app.get("/api/v1/heatmap/{symbol}")
async def get_heatmap(
@ -519,8 +506,7 @@ def create_app(config_obj=None) -> FastAPI:
static_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "web", "static")
if os.path.exists(static_path):
app.mount("/static", StaticFiles(directory=static_path), name="static")
# Serve index.html at root for dashboard, but this should be last
app.mount("/", StaticFiles(directory=static_path, html=True), name="dashboard")
# Don't mount at root to avoid conflicts with WebSocket and API routes
return app