Coverage for dj/api/main.py: 100%
39 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-17 20:05 -0700
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-17 20:05 -0700
1"""
2Main DJ server app.
3"""
5# All the models need to be imported here so that SQLModel can define their
6# relationships at runtime without causing circular imports.
7# See https://sqlmodel.tiangolo.com/tutorial/code-structure/#make-circular-imports-work.
8# pylint: disable=unused-import
10import logging
11from typing import TYPE_CHECKING, Optional
13from fastapi import Depends, FastAPI, Request
14from fastapi.responses import JSONResponse
15from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
16from starlette.middleware.cors import CORSMiddleware
18from dj import __version__
19from dj.api import (
20 attributes,
21 catalogs,
22 cubes,
23 data,
24 engines,
25 health,
26 metrics,
27 namespaces,
28 nodes,
29 query,
30 sql,
31 tags,
32)
33from dj.api.attributes import default_attribute_types
34from dj.errors import DJException
35from dj.models.catalog import Catalog
36from dj.models.column import Column
37from dj.models.engine import Engine
38from dj.models.node import NodeRevision
39from dj.models.table import Table
40from dj.utils import get_settings
42if TYPE_CHECKING: # pragma: no cover
43 from opentelemetry import trace
45_logger = logging.getLogger(__name__)
48def get_dj_app(
49 tracer_provider: Optional["trace.TracerProvider"] = None,
50) -> FastAPI:
51 """
52 Get the DJ FastAPI app and optionally inject an OpenTelemetry tracer provider
53 """
54 settings = get_settings()
55 application = FastAPI(
56 title=settings.name,
57 description=settings.description,
58 version=__version__,
59 license_info={
60 "name": "MIT License",
61 "url": "https://mit-license.org/",
62 },
63 dependencies=[Depends(default_attribute_types)],
64 )
65 application.add_middleware(
66 CORSMiddleware,
67 allow_origins=settings.cors_origin_whitelist,
68 allow_credentials=True,
69 allow_methods=["*"],
70 allow_headers=["*"],
71 )
73 application.include_router(catalogs.router)
74 application.include_router(engines.router)
75 application.include_router(metrics.router)
76 application.include_router(query.router)
77 application.include_router(nodes.router)
78 application.include_router(namespaces.router)
79 application.include_router(data.router)
80 application.include_router(health.router)
81 application.include_router(cubes.router)
82 application.include_router(tags.router)
83 application.include_router(attributes.router)
84 application.include_router(sql.router)
86 @application.exception_handler(DJException)
87 async def dj_exception_handler( # pylint: disable=unused-argument
88 request: Request,
89 exc: DJException,
90 ) -> JSONResponse:
91 """
92 Capture errors and return JSON.
93 """
94 return JSONResponse(
95 status_code=exc.http_status_code,
96 content=exc.to_dict(),
97 headers={"X-DJ-Error": "true", "X-DBAPI-Exception": exc.dbapi_exception},
98 )
100 FastAPIInstrumentor.instrument_app(application, tracer_provider=tracer_provider)
102 return application
105app = get_dj_app()