Really-amin's picture
Upload 295 files
d6d843f verified
"""Simple FastAPI server for testing HF integration"""
import asyncio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
import uvicorn
# Create FastAPI app
app = FastAPI(title="Crypto API Monitor - Simple", version="1.0.0")
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include HF router
try:
from backend.routers import hf_connect
app.include_router(hf_connect.router)
print("βœ“ HF router loaded")
except Exception as e:
print(f"βœ— HF router failed: {e}")
# Background task for HF registry
@app.on_event("startup")
async def startup_hf():
try:
from backend.services.hf_registry import periodic_refresh
asyncio.create_task(periodic_refresh())
print("βœ“ HF background refresh started")
except Exception as e:
print(f"βœ— HF background refresh failed: {e}")
# Health endpoint
@app.get("/health")
async def health():
return {"status": "healthy", "service": "crypto-api-monitor"}
@app.get("/api/health")
async def api_health():
return {"status": "healthy", "service": "crypto-api-monitor-api"}
# Serve static files
@app.get("/")
async def root():
return FileResponse("index.html")
@app.get("/index.html")
async def index():
return FileResponse("index.html")
@app.get("/hf_console.html")
async def hf_console():
return FileResponse("hf_console.html")
# Mock API endpoints for dashboard
@app.get("/api/status")
async def api_status():
"""Mock status endpoint"""
return {
"total_providers": 9,
"online": 7,
"degraded": 1,
"offline": 1,
"avg_response_time_ms": 245,
"total_requests_hour": 156,
"total_failures_hour": 3,
"system_health": "healthy",
"timestamp": "2025-11-11T01:30:00Z"
}
@app.get("/api/categories")
async def api_categories():
"""Mock categories endpoint"""
return [
{
"name": "market_data",
"total_sources": 3,
"online_sources": 3,
"avg_response_time_ms": 180,
"rate_limited_count": 0,
"last_updated": "2025-11-11T01:30:00Z",
"status": "online"
},
{
"name": "blockchain_explorers",
"total_sources": 3,
"online_sources": 2,
"avg_response_time_ms": 320,
"rate_limited_count": 1,
"last_updated": "2025-11-11T01:29:00Z",
"status": "online"
},
{
"name": "news",
"total_sources": 2,
"online_sources": 2,
"avg_response_time_ms": 450,
"rate_limited_count": 0,
"last_updated": "2025-11-11T01:28:00Z",
"status": "online"
},
{
"name": "sentiment",
"total_sources": 1,
"online_sources": 1,
"avg_response_time_ms": 200,
"rate_limited_count": 0,
"last_updated": "2025-11-11T01:30:00Z",
"status": "online"
}
]
@app.get("/api/providers")
async def api_providers():
"""Mock providers endpoint"""
return [
{
"id": 1,
"name": "CoinGecko",
"category": "market_data",
"status": "online",
"response_time_ms": 150,
"last_fetch": "2025-11-11T01:30:00Z",
"has_key": False,
"rate_limit": None
},
{
"id": 2,
"name": "Binance",
"category": "market_data",
"status": "online",
"response_time_ms": 120,
"last_fetch": "2025-11-11T01:30:00Z",
"has_key": False,
"rate_limit": None
},
{
"id": 3,
"name": "Alternative.me",
"category": "sentiment",
"status": "online",
"response_time_ms": 200,
"last_fetch": "2025-11-11T01:29:00Z",
"has_key": False,
"rate_limit": None
},
{
"id": 4,
"name": "Etherscan",
"category": "blockchain_explorers",
"status": "online",
"response_time_ms": 280,
"last_fetch": "2025-11-11T01:29:30Z",
"has_key": True,
"rate_limit": {"used": 45, "total": 100}
},
{
"id": 5,
"name": "CryptoPanic",
"category": "news",
"status": "online",
"response_time_ms": 380,
"last_fetch": "2025-11-11T01:28:00Z",
"has_key": False,
"rate_limit": None
}
]
@app.get("/api/charts/health-history")
async def api_health_history(hours: int = 24):
"""Mock health history chart data"""
import random
from datetime import datetime, timedelta
now = datetime.now()
timestamps = [(now - timedelta(hours=i)).isoformat() for i in range(23, -1, -1)]
return {
"timestamps": timestamps,
"success_rate": [random.randint(85, 100) for _ in range(24)]
}
@app.get("/api/charts/compliance")
async def api_compliance(days: int = 7):
"""Mock compliance chart data"""
import random
from datetime import datetime, timedelta
now = datetime.now()
dates = [(now - timedelta(days=i)).strftime("%a") for i in range(6, -1, -1)]
return {
"dates": dates,
"compliance_percentage": [random.randint(90, 100) for _ in range(7)]
}
@app.get("/api/logs")
async def api_logs():
"""Mock logs endpoint"""
return [
{
"timestamp": "2025-11-11T01:30:00Z",
"provider": "CoinGecko",
"endpoint": "/api/v3/ping",
"status": "success",
"response_time_ms": 150,
"http_code": 200,
"error_message": None
},
{
"timestamp": "2025-11-11T01:29:30Z",
"provider": "Binance",
"endpoint": "/api/v3/klines",
"status": "success",
"response_time_ms": 120,
"http_code": 200,
"error_message": None
},
{
"timestamp": "2025-11-11T01:29:00Z",
"provider": "Alternative.me",
"endpoint": "/fng/",
"status": "success",
"response_time_ms": 200,
"http_code": 200,
"error_message": None
}
]
@app.get("/api/rate-limits")
async def api_rate_limits():
"""Mock rate limits endpoint"""
return [
{
"provider": "CoinGecko",
"limit_type": "per_minute",
"limit_value": 50,
"current_usage": 12,
"percentage": 24.0,
"reset_in_seconds": 45
},
{
"provider": "Etherscan",
"limit_type": "per_second",
"limit_value": 5,
"current_usage": 3,
"percentage": 60.0,
"reset_in_seconds": 1
}
]
@app.get("/api/charts/rate-limit-history")
async def api_rate_limit_history(hours: int = 24):
"""Mock rate limit history chart data"""
import random
from datetime import datetime, timedelta
now = datetime.now()
timestamps = [(now - timedelta(hours=i)).strftime("%H:00") for i in range(23, -1, -1)]
return {
"timestamps": timestamps,
"providers": {
"CoinGecko": [random.randint(10, 40) for _ in range(24)],
"Etherscan": [random.randint(40, 80) for _ in range(24)]
}
}
@app.get("/api/schedule")
async def api_schedule():
"""Mock schedule endpoint"""
return [
{
"provider": "CoinGecko",
"category": "market_data",
"schedule": "every_1_min",
"last_run": "2025-11-11T01:30:00Z",
"next_run": "2025-11-11T01:31:00Z",
"on_time_percentage": 98.5,
"status": "active"
},
{
"provider": "Binance",
"category": "market_data",
"schedule": "every_1_min",
"last_run": "2025-11-11T01:30:00Z",
"next_run": "2025-11-11T01:31:00Z",
"on_time_percentage": 99.2,
"status": "active"
},
{
"provider": "Alternative.me",
"category": "sentiment",
"schedule": "every_15_min",
"last_run": "2025-11-11T01:15:00Z",
"next_run": "2025-11-11T01:30:00Z",
"on_time_percentage": 97.8,
"status": "active"
}
]
@app.get("/api/freshness")
async def api_freshness():
"""Mock freshness endpoint"""
return [
{
"provider": "CoinGecko",
"category": "market_data",
"fetch_time": "2025-11-11T01:30:00Z",
"data_timestamp": "2025-11-11T01:29:55Z",
"staleness_minutes": 0.08,
"ttl_minutes": 5,
"status": "fresh"
},
{
"provider": "Binance",
"category": "market_data",
"fetch_time": "2025-11-11T01:30:00Z",
"data_timestamp": "2025-11-11T01:29:58Z",
"staleness_minutes": 0.03,
"ttl_minutes": 5,
"status": "fresh"
}
]
@app.get("/api/failures")
async def api_failures():
"""Mock failures endpoint"""
return {
"recent_failures": [
{
"timestamp": "2025-11-11T01:25:00Z",
"provider": "NewsAPI",
"error_type": "timeout",
"error_message": "Request timeout after 10s",
"retry_attempted": True,
"retry_result": "success"
}
],
"error_type_distribution": {
"timeout": 2,
"rate_limit": 1,
"connection_error": 0
},
"top_failing_providers": [
{"provider": "NewsAPI", "failure_count": 2},
{"provider": "TronScan", "failure_count": 1}
],
"remediation_suggestions": [
{
"provider": "NewsAPI",
"issue": "Frequent timeouts",
"suggestion": "Consider increasing timeout threshold or checking network connectivity"
}
]
}
@app.get("/api/charts/freshness-history")
async def api_freshness_history(hours: int = 24):
"""Mock freshness history chart data"""
import random
from datetime import datetime, timedelta
now = datetime.now()
timestamps = [(now - timedelta(hours=i)).strftime("%H:00") for i in range(23, -1, -1)]
return {
"timestamps": timestamps,
"providers": {
"CoinGecko": [random.uniform(0.1, 2.0) for _ in range(24)],
"Binance": [random.uniform(0.05, 1.5) for _ in range(24)]
}
}
@app.get("/api/config/keys")
async def api_config_keys():
"""Mock API keys config"""
return [
{
"provider": "Etherscan",
"key_masked": "YourApiKeyToken...abc123",
"expires_at": None,
"status": "active"
},
{
"provider": "CoinMarketCap",
"key_masked": "b54bcf4d-1bca...xyz789",
"expires_at": "2025-12-31",
"status": "active"
}
]
if __name__ == "__main__":
print("=" * 70)
print("πŸš€ Starting Crypto API Monitor - Simple Server")
print("=" * 70)
print("πŸ“ Server: http://localhost:7860")
print("πŸ“„ Main Dashboard: http://localhost:7860/index.html")
print("πŸ€— HF Console: http://localhost:7860/hf_console.html")
print("πŸ“š API Docs: http://localhost:7860/docs")
print("=" * 70)
print()
uvicorn.run(
app,
host="0.0.0.0",
port=7860,
log_level="info"
)