feat(alerts): 添加微信告警、WebSocket实时推送和地图功能
- 新增微信告警服务(wechat_service)和告警任务(alert_tasks) - 新增 WebSocket 实时推送端点 - 新增监控管理模块(monitor) - 增强统计仪表板:趋势图、区域分布、光功率历史 - 设备管理:添加坐标信息、标签系统、复合索引优化 - 前端:重构Dashboard/Charts页面,新增业务组件 - 新增5个数据库迁移(坐标、复合索引、标签、光功率历史、显示名) - 更新部署配置和脚本 - 新增测试框架基础结构
This commit is contained in:
+69
-5
@@ -1,15 +1,52 @@
|
||||
"""FastAPI 主应用"""
|
||||
from fastapi import FastAPI
|
||||
import logging
|
||||
from pythonjsonlogger import jsonlogger
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from slowapi import Limiter, _rate_limit_exceeded_handler
|
||||
from slowapi.util import get_remote_address
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.responses import JSONResponse
|
||||
from app.core.config import settings
|
||||
from app.api.v1 import auth, devices, check, import_data, stats, olt, provision, users, roles, inventory, settings as settings_api, audit
|
||||
from app.api.v1 import auth, devices, check, import_data, stats, olt, provision, users, roles, inventory, settings as settings_api, audit, wechat, ws, monitor
|
||||
from app.middleware.audit_middleware import AuditMiddleware
|
||||
|
||||
app = FastAPI(title=settings.APP_NAME, debug=settings.DEBUG)
|
||||
# 结构化 JSON 日志
|
||||
_handler = logging.StreamHandler()
|
||||
_handler.setFormatter(jsonlogger.JsonFormatter('%(asctime)s %(name)s %(levelname)s %(message)s'))
|
||||
logging.getLogger().handlers = [_handler]
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
logging.getLogger('uvicorn.access').handlers = [_handler]
|
||||
|
||||
# 请求体大小限制中间件
|
||||
MAX_BODY_SIZE = 10 * 1024 * 1024 # 10 MB
|
||||
|
||||
class RequestSizeLimitMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
if request.headers.get("content-length"):
|
||||
if int(request.headers["content-length"]) > MAX_BODY_SIZE:
|
||||
return JSONResponse({"detail": "请求体过大,最大 10MB"}, status_code=413)
|
||||
return await call_next(request)
|
||||
|
||||
# CORS 白名单
|
||||
ALLOWED_ORIGINS = [
|
||||
"http://localhost:5173",
|
||||
"http://localhost:18002",
|
||||
"https://onu.dhdx.fun",
|
||||
]
|
||||
allowed = [o for o in ALLOWED_ORIGINS if o]
|
||||
|
||||
limiter = Limiter(key_func=get_remote_address, default_limits=["120/minute"])
|
||||
|
||||
app = FastAPI(title=settings.APP_NAME, debug=settings.DEBUG)
|
||||
app.state.limiter = limiter
|
||||
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
|
||||
|
||||
app.add_middleware(RequestSizeLimitMiddleware)
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_origins=allowed if allowed else ["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
@@ -28,8 +65,35 @@ app.include_router(roles.router)
|
||||
app.include_router(inventory.router)
|
||||
app.include_router(settings_api.router)
|
||||
app.include_router(audit.router)
|
||||
app.include_router(wechat.router)
|
||||
app.include_router(ws.router)
|
||||
app.include_router(monitor.router)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup():
|
||||
import asyncio
|
||||
asyncio.create_task(ws._redis_listener())
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health_check():
|
||||
return {"status": "ok"}
|
||||
status = {"status": "ok", "db": "ok", "redis": "ok"}
|
||||
try:
|
||||
import redis
|
||||
import psycopg2
|
||||
r = redis.from_url(settings.REDIS_URL, socket_timeout=2)
|
||||
r.ping()
|
||||
except Exception:
|
||||
status["redis"] = "error"
|
||||
status["status"] = "degraded"
|
||||
try:
|
||||
from sqlalchemy import text
|
||||
from app.core.database import SessionLocal
|
||||
db = SessionLocal()
|
||||
db.execute(text("SELECT 1"))
|
||||
db.close()
|
||||
except Exception:
|
||||
status["db"] = "error"
|
||||
status["status"] = "degraded"
|
||||
return status
|
||||
|
||||
Reference in New Issue
Block a user