- GET /api/metrics renders Prometheus text (equity, P&L, per-strategy equity/pnl/allocation/halted, info) with no client library. - In-memory ring log handler (app/logs.py) exposed at GET /api/logs and a dashboard "Server logs" panel; Runtime mirrors bot events into the logger. - docs/runbook.md covers deploys, the kill switch, resetting paper state and going live. Adds tests for metrics rendering and the log ring.
53 lines
1.4 KiB
Python
53 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from collections.abc import AsyncIterator
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from app.api.routes import router
|
|
from app.config import Settings, get_settings
|
|
from app.db import init_db
|
|
from app.logs import install_log_capture
|
|
from app.runtime import Runtime
|
|
|
|
|
|
def create_app(
|
|
settings: Settings | None = None,
|
|
runtime: Runtime | None = None,
|
|
) -> FastAPI:
|
|
settings = settings or get_settings()
|
|
runtime = runtime or Runtime(settings)
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
install_log_capture()
|
|
init_db()
|
|
app.state.runtime = runtime
|
|
yield
|
|
await runtime.shutdown()
|
|
|
|
app = FastAPI(title=settings.app_name, lifespan=lifespan)
|
|
# Baked at build time (see Dockerfile); the frontend compares its own
|
|
# version against this to self-heal from a stale cache.
|
|
app.state.build_version = os.environ.get("BUILD_VERSION", "unknown")
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.cors_origin_list,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
app.include_router(router)
|
|
|
|
@app.get("/")
|
|
def root() -> dict[str, str]:
|
|
return {"name": settings.app_name, "docs": "/docs"}
|
|
|
|
return app
|
|
|
|
|
|
app = create_app()
|